java创建线程哪种方法最好,【并发那些事 】创建线程的三种方式,线程的三种实现方式...

本文详细介绍了Java中通过继承Thread类、实现Runable接口和FutureTask创建线程的三种方法,分析了它们的优缺点、复杂度和可扩展性,并给出了适用场景的建议,最后强调了实际项目中推荐使用线程池的实践。
摘要由CSDN通过智能技术生成

【并发那些事 】创建线程的三种方式,线程的三种实现方式

81d04cdba7d8fe2ec6ddf41a49200f2e.png

创建线程可以说是并发知识中最基础的操作了,JDK 提供的创建线程的方式,如果不包括通过线程池的话,目前有三种形式,它们分别是通过继承 Thread 类,通过实现 Runable 接口,通过 FutureTask。如下图所示

c4fd40699bbeb872b2bfcf79719de582.png

下面整理了一下 3 种方法的具体使用与异同。

创建线程的 3 种方法

1. 继承 Thread

class MyThread extends Thread {

@Override

public void run() {

String threadName = getName();

for (int i = 0; i < 20; i++) {

System.out.println("线程[" + threadName + "]运行开始,i = " + i + " time = " + new Date());

}

}

}

MyThread myThread1 = new MyThread();

MyThread myThread2 = new MyThread();

myThread1.start();

myThread2.start();

String threadName = Thread.currentThread().getName();

for (int i = 0; i < 20; i++) {

System.out.println("线程[" + threadName + "]运行开始,i = " + i + " time = " + new Date());

}

整体流程如下:

这里步骤比较简单和清晰

2. 实现 Runable

class MyRunable implements Runnable {

@Override

public void run() {

String threadName = Thread.currentThread().getName();

for (int i = 0; i < 20; i++) {

System.out.println("线程[" + threadName + "]运行开始,i = " + i + " time = " + new Date());

}

}

}

MyRunable myRunable = new MyRunable();

new Thread(myRunable).start();

new Thread(myRunable).start();

String threadName = Thread.currentThread().getName();

for (int i = 0; i < 20; i++) {

System.out.println("线程[" + threadName + "]运行开始,i = " + i + " time = " + new Date());

}

整体流程如下:

具体步骤如下:

3. 通过 FutureTask

class MyCallerTask implements Callable {

@Override

public String call() throws Exception {

System.out.println("执行任务开始");

Thread.sleep(3000);

System.out.println("执行任务结束");

return "hello";

}

}

// 创建异步任务

FutureTask futureTask = new FutureTask<>(new MyCallerTask());

// 启动线程

new Thread(futureTask).start();

System.out.println("其它操作");

try {

// 等待任务执行完,并获得任务执行完的结果

String result = futureTask.get();

System.out.println(result);

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

整体流程如下:

具体步骤如下:

3种方法的优缺点

通过上述的演示代码,可以看出这 3 种方法,其实各有优缺点

复杂程度

通过代码量与逻辑可以明显感觉出来,第一种直接继承 Thread 最方便,并且其它两种到最后,还是要依赖创建 Thread 才能实现。所以从方便及难易程度来看,可以得到如下结论:

可扩展性

通过演示代码可以看出,只有第一种是通过继承,其它两种是通过实现接口的形式。我们都知道 JAVA 是不允许多继承,但是可以多实现。所以如果使用了第一种方法,就无法再继承别的类了。另外第一种把线程与线程任务冗余在了一起,不利于后期的维护。所以可以得到如下结论:

是否有返回值

从代码中可以很容易看出,只有通过 FutureTask 的方式才有返回值,另外两种均没有,所以得出如下结论

该用哪种方式创建线程

如果要用到返回值,那不用想,肯定只能使用 FutureTask 的方法。如果对于返回值没有要求,那Thread 与  Runable 均可,不过,考虑到可扩展性,最好使用 Runable 的形式。不过,话说回来,如果在真正项目中使用,综合考虑,一般还是最推荐通过线程池去创建。

相关文章暂无相关文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值