Java 创建线程的三种方式
在java中,目前创建线程的一共有三种形式:
1. 使用Thread类创建线程
2. 使用Runnable接口创建线程
3. 使用Callable接口和Future类创建线程
使用Thread类创建线程:
使用Thread类创建线程是三种方法里面最简单的,因为直接继承了Thread类,当继承Thread类创建了一个对象,这个对象便是线程对象
class FristThread extends Thread{ //继承Thread类 private int i; public FristThread(int i){ this.i = i; } public void run(){ //重写Run方法,并编写线程执行体 for(;i<100;i++){ System.out.println(this.getName() +" "+ i); } } } public class Threads{ public static void main(String[] args){ for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); if(i == 20){ new FristThread(i).start(); //创建线程并调用 new FristThread(i).start(); } } } }
使用Runnable接口创建线程:
使用Runnable接口创建线程,比使用Thread类创建线程要复杂一些。步骤如下:
1. 定义Runnable接口实现类,并重写run方法,该方法内放入线程执行体
2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象
说简单点,继承Runnable接口实现类只是编写线程执行程序(线程执行体),并将线程执行程序赋值到Thread对象的run方法,真正线程对象依然是Thread类(或是继承Thread实现类)的实例,
class SecondeThread implements Runnable{ //Runnable接口实现类 private int i; @Override public void run() { // TODO Auto-generated method stub for(;i<100;i++){ System.out.println(Thread.currentThread() +" "+ i); } } } public class Threads{ public static void main(String[] args){ for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); if(i == 40){ SecondeThread st = new SecondeThread(); //创建实现类的实例 new Thread(st).start(); //创建线程,调用实现类的实例,并运行 new Thread(st).start(); } } } }
使用Callable接口和Future接口创建线程:
使用Callable接口和Future类创建线程是三种方法中创建线程最复杂,步骤如下:
1.创建Callable接口的实现类,并重写call()方法,该call()方法作为线程执行体,可以有返回值,可以声明抛出异常,Java 8开始可以直接使用Lambda表达式创建Callable对象
2.使用FutureTask类来包装Callable对象,FutureTask类继承了Future接口以及Runnable接口,Future接口用于获取Callable接口call()方法的返回值
3.使用FutureTask对象作为Thread的target创建并启动线程,一个FutureTask对象只能创建一个线程
4.使用FutureTask对象的get()方法获取子线程执行结束后的返回值
class ThirdThread implements Callable{ private int i; @Override public Object call() throws Exception { // TODO Auto-generated method stub for(;i<100;i++){ System.out.println(Thread.currentThread() +" "+ i); } return i; } } public class Threads{ public static void main(String[] args){ for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); if(i == 60){ ThirdThread tt = new ThirdThread(); FutureTask<Integer> task = new FutureTask<Integer>(tt); // FutureTask<Integer> task1 = new FutureTask<Integer>(tt); new Thread(task,"有返回值的线程1").start(); new Thread(task,"有返回值的线程2").start(); try { System.out.println("子线程返回值:"+task.get()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
总结:
为什么会有三种创建线程的方式,原因如下:
1.类只能继承一个父类,但可以继承多个接口。如果一个类要继承一个父类,那么就不能继承Thread类来创建线程,因此有了实现继承接口来创建线程,这就是1与2和3的区别。
2.方法2 和方法3都是继承接口的形式来创建线程,区别在于,方法二是重写了Run方法,没有返回值,而方法三是重写了call方法,是有返回值的,只是返回值需要线程执行体执行完后才返回。
鉴于上面分析:若要创建线程,最好采用继承Runnale或者Callable接口形式会更好一些。
PS 完整代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * 线程 * */ class FristThread extends Thread{ private int i; public FristThread(int i){ this.i = i; } public void run(){ for(;i<100;i++){ System.out.println(this.getName() +" "+ i); } } } class SecondeThread implements Runnable{ private int i; @Override public void run() { // TODO Auto-generated method stub for(;i<100;i++){ System.out.println(Thread.currentThread() +" "+ i); } } } class ThirdThread implements Callable{ private int i; @Override public Object call() throws Exception { // TODO Auto-generated method stub for(;i<100;i++){ System.out.println(Thread.currentThread() +" "+ i); } return i; } } public class Threads{ public static void main(String[] args){ for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+" "+i); if(i == 20){ new FristThread(i).start(); new FristThread(i).start(); }else if(i == 40){ SecondeThread st = new SecondeThread(); new Thread(st).start(); new Thread(st).start(); }else if(i == 60){ ThirdThread tt = new ThirdThread(); FutureTask<Integer> task = new FutureTask<Integer>(tt); // FutureTask<Integer> task1 = new FutureTask<Integer>(tt); new Thread(task,"有返回值的线程1").start(); new Thread(task,"有返回值的线程2").start(); try { System.out.println("子线程返回值:"+task.get()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }