今天简单说一下Java三种多线程实现方式和区别,主要有实现Runnable、Callable和继承Thread三种方式。java
实现Runnable的方式多线程
这种方式比较经常使用,当咱们的线程类有继承其余的类的状况下(Java不支持类多继承),而且线程任务不须要返回值的状况下能够选用这种方式。ide
1 public class ThreadRunnableDemo implements Runnable{ 2 3 /** 计数变量 */ 4 private int count = 0; 5 6 public static void main(String[] args) throws InterruptedException { 7 8 ThreadRunnableDemo threadRunnableDemo = new ThreadRunnableDemo(); 9 10 //实例化线程 11 Thread thread = new Thread(threadRunnableDemo, "threadRunnableDemoA"); 12 System.out.println(String.format("线程状态preStart: %s", thread.getState())); 13 14 //启动线程 15 thread.start(); 16 System.out.println(String.format("线程状态afterStart: %s", thread.getState())); 17 18 //主线程休眠1000ms 19 Thread.sleep(1000); 20 System.out.println(String.format("线程状态after1000ms: %s", thread.getState())); 21 22 } 23 24 @Override 25 public void run() { 26 27 count++; 28 29 System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", 30 Thread.currentThread().getName(), Thread.currentThread().getState(), count)); 31 32 } 33 }
输出结果:测试
1 线程状态preStart: NEW 2 线程状态afterStart: RUNNABLE 3 线程名称:threadRunnableDemoA, 线程状态:RUNNABLE, count:1 4 线程状态after1000ms: TERMINATED
实现Callable的方式spa
当咱们执行线程须要返回值的时候那么就必须选用实现Callable类的方式,由于目前只有这种方式能返回值。固然这种方式咱们也能够不须要获取返回值。线程
这种方式是经过FutureTask的get()方法(下面代码的第22行)或者get(long timeout, TimeUnit unit)(下面代码的第28行)方法获取返回值。当咱们看Callable的接口定义的源码会发现“public interface Callable<V> ” ,咱们实现的时候是须要定义返回类型,以下面代码所示。code
除此以外咱们还须要注意的是:当咱们经过FutureTask的get()方法去获取线程的返回值的时候是要等到线程call()内容都执行完毕以后才能获取获得,而且get()方法后面的代码必须等待,说明这必定是同步的,因此咱们能够在真正须要线程返回值的时候才经过get()方法去获取,以避免被阻塞。当咱们经过get(long timeout, TimeUnit unit)方式去获取的时候能够设置超时时间,若是超过所设置的超时时间都没有获取到线程返回的值则会抛出 java.util.concurrent.TimeoutException 异常,固然若是在get(long timeout, TimeUnit unit)以前用get()方式获取了的话就不会抛异常。orm
实现Callable还有个好处就是能够线程能够抛异常,若是咱们须要在线程里抛出异常的话也能够选用这种方式,其余两种方式只能捕获异常信息。blog
1 public class ThreadCallableDemo implements Callable<Integer>{ 2 3 /** 计数变量 */ 4 private int count = 0; 5 6 public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException { 7 8 ThreadCallableDemo threadCallableDemo = new ThreadCallableDemo(); 9 10 //经过FutureTask获取返回值 11 FutureTask<Integer> taskA = new FutureTask<>(threadCallableDemo); 12 13 //实例化线程 14 Thread thread = new Thread(taskA, "threadCallableDemoA"); 15 System.out.println(String.format("线程状态preStart: %s", thread.getState())); 16 17 //启动线程 18 thread.start(); 19 System.out.println(String.format("线程状态afterStart: %s", thread.getState())); 20 21 //经过FutureTask的get()方法获取返回值 22 int result = taskA.get(); 23 System.out.println("是否同步测试...."); 24 System.out.println(String.format("result: %s", result)); 25 System.out.println(String.format("线程状态afterGetResult1: %s", thread.getState())); 26 27 //经过FutureTask的get()方法获取返回值 设置超时时间 单位为ms 28 int resultWithTime = taskA.get(100, TimeUnit.MILLISECONDS); 29 System.out.println(String.format("resultWithTime: %s", resultWithTime)); 30 System.out.println(String.format("线程状态afterGetResult2: %s", thread.getState())); 31 32 } 33 34 /** 35 * 实现Callable的call类 36 */ 37 @Override 38 public Integer call() throws Exception { 39 40 //自增 41 count++; 42 43 System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", 44 Thread.currentThread().getName(), Thread.currentThread().getState(), count)); 45 System.out.println("休眠1000ms...."); 46 Thread.currentThread().sleep(1000); 47 return count; 48 } 49 }
输出结果:继承
1 线程状态preStart: NEW 2 线程状态afterStart: RUNNABLE 3 线程名称:threadCallableDemoA, 线程状态:RUNNABLE, count:1 4 休眠1000ms.... 5 是否同步测试.... 6 result: 1 7 线程状态afterGetResult1: TERMINATED 8 resultWithTime: 1 9 线程状态afterGetResult2: TERMINATED
继承Thread的方式
Thread类实际上也是实现Runnable接口,因此当咱们继承Thread的时候咱们即便不实现run()方法也不会报错,这种方式也常常用。
下面我写了两种不一样继承Thread的代码,你们能够看一下区别,我在网上看到不少人说 继承Thread实现多线程,线程间不能共享数据,可是我用下面的代码1方式彷佛也能够共享哇,欢迎你们提出质疑。
代码1:
1 public class ThreadThreadDemo extends Thread{ 2 3 /** 计数变量 */ 4 private int count = 0; 5 6 public static void main(String[] args) throws InterruptedException { 7 8 ThreadThreadDemo threadThreadDemo = new ThreadThreadDemo(); 9 10 //实例化线程 11 Thread thread = new Thread(threadThreadDemo, "threadThreadDemoA"); 12 System.out.println(String.format("线程状态preStart: %s", thread.getState())); 13 14 //启动线程 15 thread.start(); 16 System.out.println(String.format("线程状态afterStart: %s", thread.getState())); 17 18 //主线程休眠1000s 19 Thread.sleep(1000); 20 System.out.println(String.format("线程状态after1000ms: %s", thread.getState())); 21 } 22 23 @Override 24 public void run() { 25 26 count++; 27 28 System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", 29 Thread.currentThread().getName(), Thread.currentThread().getState(), count)); 30 } 31 }
输出结果1:
1 线程状态preStart: NEW 2 线程状态afterStart: RUNNABLE 3 线程名称:threadThreadDemoA, 线程状态:RUNNABLE, count:1 4 线程状态after1000ms: TERMINATED
代码2:
1 public class ThreadThreadDemo extends Thread{ 2 3 /** 计数变量 */ 4 private int count = 0; 5 6 public static void main(String[] args) throws InterruptedException { 7 8 ThreadThreadDemo threadThreadDemo = new ThreadThreadDemo(); 9 10 //实例化线程 11 System.out.println(String.format("线程状态preStart: %s", threadThreadDemo.getState())); 12 13 //启动线程 14 threadThreadDemo.start(); 15 System.out.println(String.format("线程状态afterStart: %s", threadThreadDemo.getState())); 16 17 //主线程休眠1000s 18 Thread.sleep(1000); 19 System.out.println(String.format("线程状态after1000ms: %s", threadThreadDemo.getState())); 20 } 21 22 @Override 23 public void run() { 24 25 count++; 26 27 System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", 28 Thread.currentThread().getName(), Thread.currentThread().getState(), count)); 29 } 30 }
输出结果2:
1 线程状态preStart: NEW 2 线程状态afterStart: RUNNABLE 3 线程名称:Thread-0, 线程状态:RUNNABLE, count:1 4 线程状态after1000ms: TERMINATED
最后总结:
若是有疑问或者有问题欢迎留言讨论!