第一种创建线程方法
public class Test {
public static void main(String[] args) {
//创建线程方法1
Thread thread = new Thread();
System.out.println("线程ID:"+thread.getId());
System.out.println("线程名称:"+thread.getName());
System.out.println("线程状态:"+thread.getState());
System.out.println("线程优先级:"+thread.getPriority());
System.out.println("是否守护线程:"+thread.isDaemon());
//启动线程
thread.start();
}
}
运行Test.class结果
线程ID:11
线程名称:Thread-0
线程状态:NEW
线程优先级:5
是否守护线程:false
第二种创建线程方法 继承Thread线程类
public class Test {
static int no = 1;
//继承Thread 实现run方法
static class ThreadTwo extends Thread{
public ThreadTwo() {
super("ThreadTwo-"+no++);
}
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(getName()+"次数:"+i);
}
}
}
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
new ThreadTwo().start();
}
}
}
运行Test.class结果
ThreadTwo-1次数:0
ThreadTwo-1次数:1
ThreadTwo-1次数:2
ThreadTwo-1次数:3
ThreadTwo-1次数:4
ThreadTwo-2次数:0
ThreadTwo-2次数:1
ThreadTwo-2次数:2
ThreadTwo-2次数:3
ThreadTwo-2次数:4
第三种创建线程方法 实现Runnable接口
public class Test {
//实现Runnable接口创建线程
static class RThread implements Runnable{
private AtomicInteger num =new AtomicInteger(5);
public RThread() {
super();
}
public void run() {
for (int i = 0; i < 5; i++) {
if (this.num.get()>0) {
System.out.println(Thread.currentThread().getName()+":"+(num.decrementAndGet()));
}
}
}
}
public static void main(String[] args) {
RThread trThread = new RThread();
for (int i = 0; i < 2; i++) {
new Thread(trThread,"线程:"+i).start();
}
}
}
运行Test.class结果
线程:0:3
线程:0:2
线程:1:4
线程:0:1
线程:1:0
对比Thread和Runnable
- 通过继承Thread类,实现多个线程并发执行各自的逻辑任务
- 通过实现Runnable接口,实现多个线程并发完成一个逻辑任务
- Runnable 出现线程不安全问题,需要共享数据使用原子类型或者添加锁
第四种创建线程方法 实通过Callable接口和FutureTask类创建线程
public class Test {
//创建Callable接口实现类
static class CRThread implements Callable<Long>{
@Override
public Long call() throws Exception {
long startNum = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"运行开始:"+startNum);
Thread.sleep(5000);
long time = System.currentTimeMillis()-startNum;
System.out.println(Thread.currentThread().getName()+"运行结束:"+time);
return time;
}
}
public static void main(String[] args) {
CRThread crThread = new CRThread();
FutureTask<Long> futureTask = new FutureTask<Long>(crThread);
System.out.println(Thread.currentThread().getName()+":执行任务");
System.out.println(Thread.currentThread().getName()+":获取线程执行结果:");
for (int i = 0; i < 2; i++) {
Thread thread = new Thread(futureTask, "crThread"+i);
thread.start();
try {
System.out.println(thread.getName()+"线程执行占用时间:"+ futureTask.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+":执行结束");
}
}
运行Test.class结果
main:执行任务
main:获取线程执行结果:
crThread0运行开始:1642044052420
crThread0运行结束:5002
crThread0线程执行占用时间:5002
crThread1线程执行占用时间:5002
main:执行结束
优点:可以获取线程执行的返回值,可以捕获异常
第五种创建线程方法 通过线程池类创建线程
//线程阻塞队列
BlockingQueue<Runnable> bQueue = new LinkedBlockingDeque<Runnable>(3);
//创建线程池
//核心线程数 3
//最大线程数 5
//阻塞队列3
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 5, 2000, TimeUnit.MILLISECONDS, bQueue);
for (int i = 0; i < 2; i++) {
poolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId()+" 运行。。。");
try {
Thread.sleep(5);
} catch (Exception e) {
}
}
});
}
运行测试
当任务小于等于核心线程数时,直接启动与任务数相同的线程数量
当任务大于核心线程数时,且小于核心线程数与阻塞队列数之和时,把大于核心线程数的任务加入到阻塞队列,等待前面的任务执行完,再从阻塞队列中获取任务,使用核心线程执行。
当任务大于核心线程数时,且大于核心线程数与阻塞队列数之和,小于核心线程数与阻塞队列数与最大线程数之和时,把大于核心线程数与阻塞队列数之和的任务通过新建线程执行,那么线程池中的线程等于核心线程与新建线程之和
当任务大于核心线程数,大于阻塞队列数和最大线程数之和时 ,程序拒绝执行任务