Java 提供了三种创建线程的方法
1.继承Thread接口
1 public class Thread2Thread { 2 public static void main(String[] args) { 3 new MyThread1().start(); 4 new Thread(new MyThread1(), "线程2").start(); 5 } 6 } 7 8 /** 9 * 通过继承Thread类 10 */ 11 class MyThread1 extends Thread { 12 /** 13 * 重写run方法 14 */ 15 @Override 16 public void run() { 17 // TODO Auto-generated method stub 18 super.run(); 19 } 20 }
2.实现Runnable接口
1 package com.testthread.demo4; 2 3 import java.util.concurrent.ExecutorService; 4 5 import static java.util.concurrent.Executors.*; 6 7 public class Thread2Runnable { 8 9 public static void main(String[] args) { 10 11 //case1:通过实现Runnable接口,来实现run方法的具体逻辑 12 new Thread(new MyThread2(), "线程1").start(); 13 //case2:匿名内部类 14 new Thread(new Runnable() { 15 @Override 16 public void run() { 17 // TODO Auto-generated method stub 18 19 } 20 }, "线程2").start(); 21 22 //其实case1和case2的本质是一样的 23 24 //case3:作为线程任务提交给线程池,通过线程池维护的工作者线程来执行。 25 ExecutorService executor = newCachedThreadPool(); 26 MyThread2 myThread2 = new MyThread2(); 27 executor.execute(myThread2); 28 executor.shutdown(); 29 } 30 } 31 32 /** 33 * 实现Runnable接口的线程类 34 */ 35 class MyThread2 implements Runnable { 36 37 /** 38 * 重写run方法 39 */ 40 @Override 41 public void run() { 42 // TODO Auto-generated method stub 43 } 44 }
3.通过Callable和Future创建线程
1 import java.util.concurrent.Callable; 2 import java.util.concurrent.FutureTask; 3 4 public class Thread2Callable { 5 public static void main(String[] args) { 6 //创建 Callable 实现类的实例 7 MyCallable myCallable = new MyCallable(); 8 //使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值 9 FutureTask<String> futureTask = new FutureTask<String>(myCallable); 10 String res = null; 11 try { 12 //使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程 13 //没这句,下句代码获取不到结果,会一直等待执行结果 14 new Thread(futureTask,"线程1").start(); 15 //调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值 16 res = futureTask.get(); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 } 20 System.out.println(res); 21 } 22 } 23 /** 24 * 创建 Callable 接口的实现类,并实现 call() 方法 25 */ 26 class MyCallable implements Callable<String> { 27 28 /** 29 * 该 call() 方法将作为线程执行体,并且有返回值 30 */ 31 @Override 32 public String call() throws Exception { 33 return "success"; 34 } 35 }
Runnable和Callable的区别和联系
接口定义
其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中,该函数没有返回值。然后使用某个线程去执行该runnable即可实现多线程,Thread类在调用start()函数后就是执行的是Runnable的run()函数。
Runnable的声明如下 :
1 public interface Runnable { 2 /* 3 * @see java.lang.Thread#run() 4 */ 5 public abstract void run(); 6 }
#Callable
Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是call()函数有返回值,而Runnable的run()函数不能将结果返回给客户程序。
Callable的声明如下 :
1 public interface Callable<V> { 2 /** 3 * Computes a result, or throws an exception if unable to do so. 4 * 5 * @return computed result 6 * @throws Exception if unable to compute a result 7 */ 8 V call() throws Exception; 9 }
#Future
Executor就是Runnable和Callable的调度容器,Future就是对于具体的Runnable或者Callable任务的执行结果进行
取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果(Future简介)。
Future声明如下 :
1 public interface Future<V> { 2 3 /** 4 * Attempts to cancel execution of this task. This attempt will 5 * fail if the task has already completed, has already been cancelled, 6 * or could not be cancelled for some other reason. If successful, 7 * and this task has not started when <tt>cancel</tt> is called, 8 * this task should never run. If the task has already started, 9 * then the <tt>mayInterruptIfRunning</tt> parameter determines 10 * whether the thread executing this task should be interrupted in 11 * an attempt to stop the task. 12 */ 13 boolean cancel(boolean mayInterruptIfRunning); 14 15 /** 16 * Returns <tt>true</tt> if this task was cancelled before it completed 17 * normally. 18 */ 19 boolean isCancelled(); 20 21 /** 22 * Returns <tt>true</tt> if this task completed. 23 * 24 */ 25 boolean isDone(); 26 27 /** 28 * Waits if necessary for the computation to complete, and then 29 * retrieves its result. 30 * 31 * @return the computed result 32 */ 33 V get() throws InterruptedException, ExecutionException; 34 35 /** 36 * Waits if necessary for at most the given time for the computation 37 * to complete, and then retrieves its result, if available. 38 * 39 * @param timeout the maximum time to wait 40 * @param unit the time unit of the timeout argument 41 * @return the computed result 42 */ 43 V get(long timeout, TimeUnit unit) 44 throws InterruptedException, ExecutionException, TimeoutException; 45 }
#FutureTask(很有用)
FutureTask是一个RunnableFuture<V>
1 public class FutureTask<V> implements RunnableFuture<V>
RunnableFuture实现了Runnbale又实现了Futrue<V>这两个接口
1 public interface RunnableFuture<V> extends Runnable, Future<V> { 2 /** 3 * Sets this Future to the result of its computation 4 * unless it has been cancelled. 5 */ 6 void run(); 7 }
另外FutureTaslk还可以包装Runnable和Callable<V>, 由构造函数注入依赖。
1 public FutureTask(Callable<V> callable) { 2 if (callable == null) 3 throw new NullPointerException(); 4 this.callable = callable; 5 this.state = NEW; // ensure visibility of callable 6 } 7 8 public FutureTask(Runnable runnable, V result) { 9 this.callable = Executors.callable(runnable, result); 10 this.state = NEW; // ensure visibility of callable 11 }
上面代码块可以看出:Runnable注入会被Executors.callable()函数转换为Callable类型,即FutureTask最终都是执行Callable类型的任务。
该适配函数的实现如下 :
1 public static <T> Callable<T> callable(Runnable task, T result) { 2 if (task == null) 3 throw new NullPointerException(); 4 return new RunnableAdapter<T>(task, result); 5 }
RunnableAdapter适配器
1 /** 2 * A callable that runs given task and returns given result 3 */ 4 static final class RunnableAdapter<T> implements Callable<T> { 5 final Runnable task; 6 final T result; 7 RunnableAdapter(Runnable task, T result) { 8 this.task = task; 9 this.result = result; 10 } 11 public T call() { 12 task.run(); 13 return result; 14 } 15 }
FutureTask实现Runnable,所以能通过Thread包装执行, FutureTask实现Runnable,所以能通过提交给ExcecuteService来执行 注:ExecuteService:创建线程池实例对象,其中有submit(Runnable)、submit(Callable)方法 ExecturService:https://blog.csdn.net/suifeng3051/article/details/49443835 还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。 因此FutureTask是Future也是Runnable,又是包装了的Callable( 如果是Runnable最终也会被转换为Callable )。
相同点
1 都是接口 2 都可以编写多线程程序 3 都采用Thread.start()启动线程
不同点
1 Callable规定的方法是call(),而Runnable规定的方法是run(). 2 Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。 3 call()方法可抛出异常,而run()方法是不能抛出异常的。--run()方法异常只能在内部消化,不能往上继续抛 4 运行Callable任务可拿到一个Future对象, Future表示异步计算的结果。 5 它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。 6 通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。 7 Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。 注:Callalbe接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞。
示例:
1 package com.xzf.callable; 2 3 import java.util.concurrent.Callable; 4 import java.util.concurrent.ExecutorService; 5 import java.util.concurrent.Executors; 6 import java.util.concurrent.Future; 7 import java.util.concurrent.FutureTask; 8 9 public class RunnableFutureTask { 10 static ExecutorService executorService = Executors.newSingleThreadExecutor(); //创建一个单线程执行器 11 public static void main(String[] args) { 12 runnableDemo(); 13 futureDemo(); 14 } 15 /** 16 * new Thread(Runnable arg0).start(); 用Thread()方法开启一个新线程 17 * runnable, 无返回值 18 */ 19 static void runnableDemo() { 20 new Thread(new Runnable() { 21 public void run() { 22 System.out.println("runnable demo:" + fibc(20)); //有值 23 } 24 25 }).start(); 26 } 27 /** 28 * Runnable实现的是void run()方法,无返回值 29 * Callable实现的是 V call()方法,并且可以返回执行结果 30 * Runnable可以提交给Thread,在包装下直接启动一个线程来执行 31 * Callable一般都是提交给ExecuteService来执行 32 */ 33 34 static void futureDemo() { 35 try { 36 Future<?> result1 = executorService.submit(new Runnable() { 37 public void run() { 38 fibc(20); 39 } 40 }); 41 System.out.println("future result from runnable:"+result1.get()); //run()无返回值所以为空,result1.get()方法会阻塞 42 Future<Integer> result2 = executorService.submit(new Callable<Integer>() { 43 public Integer call() throws Exception { 44 return fibc(20); 45 } 46 }); 47 System.out.println("future result from callable:"+result2.get()); //call()有返回值,result2.get()方法会阻塞 48 FutureTask<Integer> result3 = new FutureTask<Integer>(new Callable<Integer>() { 49 public Integer call() throws Exception { 50 return fibc(20); 51 } 52 }); 53 executorService.submit(result3); 54 System.out.println("future result from FutureTask:" + result3.get()); //call()有返回值,result3.get()方法会阻塞 55 56 /*因为FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行*/ 57 FutureTask<Integer> result4 = new FutureTask<Integer>(new Runnable() { 58 public void run() { 59 fibc(20); 60 } 61 },fibc(20)); 62 executorService.submit(result4); 63 System.out.println("future result from executeService FutureTask :" + result4.get()); //call()有返回值,result3.get()方法会阻塞 64 //这里解释一下什么FutureTask实现了Runnable结果不为null,这就用到FutureTask对Runnable的包装,所以Runnable注入会被Executors.callable()函数转换成Callable类型 65 66 FutureTask<Integer> result5 = new FutureTask<Integer>(new Runnable() { 67 public void run() { 68 fibc(20); 69 } 70 },fibc(20)); 71 new Thread(result5).start(); 72 System.out.println("future result from Thread FutureTask :" + result5.get()); //call()有返回值,result5.get()方法会阻塞 73 74 } catch (Exception e) { 75 e.printStackTrace(); 76 }finally { 77 executorService.shutdown(); 78 } 79 } 80 static int fibc(int num) { 81 if (num==0) { 82 return 0; 83 } 84 if (num==1) { 85 return 1; 86 } 87 return fibc(num-1) + fibc(num-2); 88 } 89 }
运行结果:
1 runnable demo:6765 2 future result from runnable:null 3 future result from callable:6765 4 future result from FutureTask:6765 5 future result from executeService FutureTask :6765 6 future result from Thread FutureTask :6765
1 package com.testthread.test; 2 3 import java.util.concurrent.*; 4 import java.util.Date; 5 import java.util.List; 6 import java.util.ArrayList; 7 8 public class Test implements Callable<Object> { 9 private String taskNum; 10 11 Test(String taskNum) { 12 this.taskNum = taskNum; 13 } 14 15 public static void main(String[] args) { 16 System.out.println("----程序开始运行----"); 17 Date date1 = new Date(); 18 int taskSize = 5; // 创建一个线程池 19 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 创建多个有返回值的任务 20 List<Future> list = new ArrayList<Future>(); 21 try { 22 for (int i = 0; i < taskSize; i++) { 23 Callable c = new Test(i + " "); // 执行任务并获取Future对象 24 Future f = pool.submit(c); 25 list.add(f); 26 } 27 // 获取所有并发任务的运行结果 28 for (Future f : list) { 29 // 从Future对象上获取任务的返回值,并输出到控制台 30 System.out.println(">>>" + f.get().toString()); 31 } 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } catch (ExecutionException e) { 35 e.printStackTrace(); 36 } finally {// 关闭线程池 37 pool.shutdown(); 38 } 39 Date date2 = new Date(); 40 System.out.println("----程序结束运行----,程序运行时间【" + (date2.getTime() - date1.getTime()) + "毫秒】"); 41 } 42 43 @Override 44 public Object call() throws Exception { 45 System.out.println(">>>" + taskNum + "任务启动"); 46 Date dateTmp1 = new Date(); 47 Thread.sleep(1000); 48 Date dateTmp2 = new Date(); 49 long time = dateTmp2.getTime() - dateTmp1.getTime(); 50 System.out.println(">>>" + taskNum + "任务终止"); 51 return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】"; 52 } 53 }
1 ----程序开始运行---- 2 >>>1 任务启动 3 >>>0 任务启动 4 >>>3 任务启动 5 >>>2 任务启动 6 >>>4 任务启动 7 >>>1 任务终止 8 >>>3 任务终止 9 >>>0 任务终止 10 >>>0 任务返回运行结果,当前任务时间【1029毫秒】 11 >>>2 任务终止 12 >>>1 任务返回运行结果,当前任务时间【1029毫秒】 13 >>>2 任务返回运行结果,当前任务时间【1030毫秒】 14 >>>3 任务返回运行结果,当前任务时间【1030毫秒】 15 >>>4 任务终止 16 >>>4 任务返回运行结果,当前任务时间【1030毫秒】 17 ----程序结束运行----,程序运行时间【1146毫秒】
1 package com.testthread.test; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 import java.util.concurrent.Callable; 8 import java.util.concurrent.ExecutionException; 9 import java.util.concurrent.ExecutorService; 10 import java.util.concurrent.FutureTask; 11 12 import static java.util.concurrent.Executors.newFixedThreadPool; 13 14 public class Test2 { 15 16 public static void main(String[] args) { 17 Map<String, Object> resultMap = new HashMap<>(); 18 int count = 10; 19 ExecutorService executorService = newFixedThreadPool(10); 20 long start = System.currentTimeMillis(); 21 try { 22 List<FutureTask> list = new ArrayList(); 23 for (int i = 0; i < count; i++) { 24 FutureTask<Map<String, Object>> result = new FutureTask<Map<String, Object>>(myCall(i + "")); 25 executorService.submit(result); 26 list.add(result); 27 } 28 for (int i = 0; i < count; i++) { 29 Map<String, Object> resultMapShow = (Map<String, Object>) list.get(i).get(); 30 System.out.println("resultMapShow = " + resultMapShow); 31 Map<String, Object> body = (Map<String, Object>) resultMapShow.get("body"); 32 resultMap.put("aa" + i, body.get("aa")); 33 } 34 System.out.println("====>took:" + (System.currentTimeMillis() - start)); 35 36 } catch (InterruptedException e) { 37 e.printStackTrace(); 38 } catch (ExecutionException e) { 39 e.printStackTrace(); 40 } finally { 41 executorService.shutdown(); 42 } 43 System.out.println("resultMap = " + resultMap); 44 System.out.println("==>took:" + (System.currentTimeMillis() - start)); 45 } 46 47 48 public static Callable<Map<String, Object>> myCall(String taskId) { 49 Callable<Map<String, Object>> callable = new Callable<Map<String, Object>>() { 50 @Override 51 public Map<String, Object> call() throws Exception { 52 return queryMethod(taskId); 53 } 54 }; 55 return callable; 56 } 57 58 private static Map<String, Object> queryMethod(String taskId) { 59 try { 60 System.out.println(" ==>任务启动" + taskId); 61 long startI = System.currentTimeMillis(); 62 Thread.sleep(500); 63 // System.out.println(" sleep:500ms"); 64 System.out.println(" ==>任务终止" + taskId + " 任务时间:" + (System.currentTimeMillis() - startI)); 65 } catch (InterruptedException e) { 66 e.printStackTrace(); 67 } 68 Map<String, Object> resultMap = new HashMap<>(); 69 Map<String, Object> head = new HashMap<>(); 70 head.put("retFlag", "0000"); 71 head.put("retMsg", "成功"); 72 Map<String, Object> body = new HashMap<>(); 73 body.put("aa", "11"); 74 resultMap.put("head", head); 75 resultMap.put("body", body); 76 return resultMap; 77 } 78 }
1 ==>任务启动0 2 ==>任务启动1 3 ==>任务启动2 4 ==>任务启动3 5 ==>任务启动4 6 ==>任务启动5 7 ==>任务启动6 8 ==>任务启动7 9 ==>任务启动8 10 ==>任务启动9 11 ==>任务终止0 任务时间:501 12 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 13 ==>任务终止4 任务时间:502 14 ==>任务终止3 任务时间:502 15 ==>任务终止2 任务时间:502 16 ==>任务终止1 任务时间:502 17 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 18 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 19 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 20 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 21 ==>任务终止6 任务时间:502 22 ==>任务终止5 任务时间:502 23 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 24 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 25 ==>任务终止8 任务时间:501 26 ==>任务终止7 任务时间:501 27 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 28 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 29 ==>任务终止9 任务时间:501 30 resultMapShow = {head={retMsg=成功, retFlag=0000}, body={aa=11}} 31 ====>took:525 32 resultMap = {aa1=11, aa0=11, aa3=11, aa2=11, aa5=11, aa4=11, aa7=11, aa6=11, aa9=11, aa8=11} 33 ==>took:526
关系图:
下面是关系图,望有助理解
转自:https://blog.csdn.net/sinat_39634657/article/details/81456810
https://blog.csdn.net/u012894692/article/details/80215140
https://blog.csdn.net/rexueqingchun/article/details/79025882