建立线程能够说是并发知识中最基础的操做了,JDK 提供的建立线程的方式,若是不包括经过线程池的话,目前有三种形式,它们分别是经过继承 Thread 类,经过实现 Runable 接口,经过 FutureTask。以下图所示java
下面整理了一下 3 种方法的具体使用与异同。多线程
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()); }
总体流程以下:并发
这里步骤比较简单和清晰异步
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()); }
总体流程以下:ide
具体步骤以下:函数
class MyCallerTask implements Callable<string> { @Override public String call() throws Exception { System.out.println("执行任务开始"); Thread.sleep(3000); System.out.println("执行任务结束"); return "hello"; } }
// 建立异步任务 FutureTask<string> 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(); }
总体流程以下:线程
具体步骤以下:3d
经过上述的演示代码,能够看出这 3 种方法,其实各有优缺点code
经过代码量与逻辑能够明显感受出来,第一种直接继承 Thread 最方便,而且其它两种到最后,仍是要依赖建立 Thread 才能实现。因此从方便及难易程度来看,能够获得以下结论: blog
经过演示代码能够看出,只有第一种是经过继承,其它两种是经过实现接口的形式。咱们都知道 JAVA 是不容许多继承,可是能够多实现。因此若是使用了第一种方法,就没法再继承别的类了。另外第一种把线程与线程任务冗余在了一块儿,不利于后期的维护。因此能够获得以下结论:
从代码中能够很容易看出,只有经过 FutureTask 的方式才有返回值,另外两种均没有,因此得出以下结论
若是要用到返回值,那不用想,确定只能使用 FutureTask 的方法。若是对于返回值没有要求,那Thread 与 Runable 都可,不过,考虑到可扩展性,最好使用 Runable 的形式。不过,话说回来,若是在真正项目中使用,综合考虑,通常仍是最推荐经过线程池去建立。
> 本文由博客一文多发平台 OpenWrite 发布! </t></string></string></t>