Callable,Runnable异同

1、Runnable和Callable的区别

(1) Callable规定的方法是 call(), Runnable规定的方法是 run()。

(2) Callable的任务执行后可返回值,而 Runnable的任务是不能返回值。

(3) call方法可以抛出异常, run方法不可以。

(4)运行 Callable任务可以拿到一个 Future对象

  Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get方法来获取结果,如果线程没有执行完, Future.get()方法可能会阻塞当前线程的执行;如果线程出现异常, Future.get()会 throws InterruptedException或者 ExecutionException;如果线程已经取消,会跑出 CancellationException。取消由 cancel方法来执行。
  isDone确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future但又不提供可用的结果,则可以声明 Future <?> 形式类型、并返回null作为底层任务的结果。

Future接口的定义如下:

  Future模式在请求发生时,会先产生一个 Future凭证给发出请求的客户,它的作用就像是 Proxy物件,同时,由一个新的执行线程持续进行目标物件的生成( Thread - Per - Message),真正的目标物件生成之后,将之设定至 Future之中,而当客户端真正需要目标物件时,目标物件也已经准备好,可以让客户提取使用。

      结合 JDK的 Future来看,就是你 run线程后,你可以把线程的返回值赋给 Future并返回一个 Future对象。这时你可以立即拿到这个对象,然后进行下面的逻辑。但是如果你要 get这个 Future中的线程结果,就会被阻塞直到线程结束。

  相当于现在的期房,你把手续和钱都交上去了,就可以马上拿到合同,但只有合同没有房子。这个时候你已经是有房一族了,你可以先去买家电买装修(走下面的其他逻辑)。但是你要把家电和装修放进去,就必须等到房子完工(阻塞)。

2、Callable实现:

  submit方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化,可以用isDone()的方法来查询Future是否已经完成。当任务完成是,它具有一个结果,可以调用get()方法来获取该结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package  zeze;
  
import  java.util.ArrayList;
import  java.util.concurrent.Callable;
import  java.util.concurrent.ExecutorService;
import  java.util.concurrent.Executors;
import  java.util.concurrent.Future;
  
/***
  *
  * @ClassName: EbayMultiplyThreadCheck
  * @Description: TODO
  * @author zeze
  * @date 2017年2月16日 上午8:49:46
  *
  */
public  class  EbayMultiplyThreadCheck {
     public  static  void  main(String[] args) {
         ExecutorService exec = Executors.newFixedThreadPool( 10 );
         ArrayList<Future<String>> results =  new  ArrayList<Future<String>>();
  
         for  ( int  i =  0 ; i <  10 ; i++) {
             String email =  "asd"  + i +  "@qq.com" ;
             results.add(exec.submit( new  TaskWithResult(email)));
         }
  
         boolean  isDone =  false ;
         while  (!isDone) {
             isDone =  true ;
             for  (Future<String> future : results) {
                 if  (!future.isDone()) {
                     isDone =  false ;
                     try  {
                         Thread.sleep( 1000 );
                     catch  (InterruptedException e) {
                     }
                     break ;
                 }
             }
         }
         exec.shutdown();
     }
}
  
class  TaskWithResult  implements  Callable<String> {
  
     private  String email;
  
     public  TaskWithResult(String email) {
         this .email = email;
     }
  
     @Override
     public  String call() {
         System.out.println(email);
         return  null ;
     }
  
}

3、Runnable 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/** 
* @Title: RunnableDemo.java
* @Package zeze
* @Description: TODO(用一句话描述该文件做什么)
* @author A18ccms A18ccms_gmail_com 
* @date 2017年3月13日 下午4:08:09
* @version V1.0 
*/
package  zeze;
  
import  java.util.concurrent.ExecutorService;
import  java.util.concurrent.Executors;
  
import  javafx.animation.Animation.Status;
  
/**
  * @ClassName: RunnableDemo
  * @Description: TODO
  * @author zeze
  * @date 2017年3月13日 下午4:08:09
  *
  */
public  class  RunnableDemo  implements  Runnable {
  
     protected  int  countDown =  10 ;
     private  static  int  taskCount =  0 ;
     private  final  int  id = taskCount++;
  
     public  RunnableDemo() {
     }
  
     public  RunnableDemo( int  countDown) {
         this .countDown = countDown;
     }
  
     public  String status() {
         return  "#"  + id +  "("  + (countDown >  0  ? countDown :  "LiftOff!" ) +  ")." ;
     }
  
     @Override
     public  void  run() {
         while  (countDown-- >  0 ) {
             System.out.print(status());
             Thread.yield(); // 将CPU从一个线程转移给另一个线程
         }
     }
  
     public  static  void  main(String[] args) {
  
         System.out.println( "这个任务的run()不是单独的线程驱动,是在main()中直接调用" );
         RunnableDemo launch =  new  RunnableDemo();
         launch.run();
         System.out.println();
         System.out.println( "************************************" );
  
         System.out.println( "在新线程中启动任务" );
         Thread thread =  new  Thread( new  RunnableDemo());
         thread.start();
         System.out.println( "Waiting for LiftOff" );
         System.out.println( "************************************" );
  
         System.out.println( "添加多个线程去驱动更多的任务" );
         for  ( int  i =  0 ; i <  5 ; i++) {
             new  Thread( new  RunnableDemo()).start();
         }
         System.out.println( "Waiting for LiftOff" );
  
         System.out.println( "************************************" );
         System.out.println( "使用executor" );
         ExecutorService exec = Executors.newCachedThreadPool();
         exec=Executors.newFixedThreadPool( 5 );
         for  ( int  i =  0 ; i <  5 ; i++) {
             exec.execute( new  RunnableDemo());
         }
         exec.shutdown();
     }
  
}

猜你喜欢

转载自www.cnblogs.com/DreamRecorder/p/9257126.html