Callable接口和Runnable接口


Callable接口和Runnable接口相似,區別就是Callable需要實現call方法,而Runnable需要實現run方法;並且,call方法還可以返回任何對象,無論是什么對象,JVM都會當作Object來處理。但是如果使用了泛型,我們就不用每次都對Object進行轉換了。

 

Runnable和Callable都是接口

不同之處:
1.Callable可以返回一個類型V,而Runnable不可以
2.Callable能夠拋出checked exception,而Runnable不可以
3.Runnable是自從java1.1就有了,而Callable是1.5之后才加上去的
4.Callable和Runnable都可以應用於executors。而Thread類只支持Runnable.
上面只是簡單的不同,其實這兩個接口在用起來差別還是很大的。Callable與executors聯合在一起,在任務完成時可立刻獲得一個更新了的Future。而Runable卻要自己處理

 

  Future接口,一般都是取回Callable執行的狀態用的。其中的主要方法:

  • cancel,取消Callable的執行,當Callable還沒有完成時
  • get,獲得Callable的返回值
  • isCanceled,判斷是否取消了
  • isDone,判斷是否完成

 

用Executor來構建線程池,應該要做的事:

1).調用Executors類中的靜態方法newCachedThreadPool(必要時創建新線程,空閑線程會被保留60秒)或newFixedThreadPool(包含固定數量的線程池)等,返回的是一個實現了ExecutorService接口的ThreadPoolExecutor類或者是一個實現了ScheduledExecutorServiece接口的類對象。

2).調用submit提交Runnable或Callable對象。

3).如果想要取消一個任務,或如果提交Callable對象,那就要保存好返回的Future對象。

4).當不再提交任何任務時,調用shutdown方法

 

在java5以后,一個可以調度執行的線程單元可以有三種方式定義:

Thread、Runnable、Callable,其中Runnable實現的是void run()方法,Callable實現的是 V call()方法,並且可以返回執行結果,其中Runnable可以提交給Thread來包裝下,直接啟動一個線程來執行,而Callable則一般都是提交給ExecuteService來執行。

簡單來說,Executor就是Runnable和Callable的調度容器,Future就是對於具體的調度任務的執行結果進行查看,最為關鍵的是Future可以檢查對應的任務是否已經完成,也可以阻塞在get方法上一直等待任務返回結果。Runnable和Callable的差別就是Runnable是沒有結果可以返回的,就算是通過Future也看不到任務調度的結果的。

 

FutureTask則是一個RunnableFuture<V>,即實現了Runnbale又實現了Futrue<V>這兩個接口,另外它還可以包裝Runnable和Callable<V>,所以一般來講是一個符合體了,它可以通過Thread包裝來直接執行,也可以提交給ExecuteService來執行,並且還可以通過v get()返回執行結果,在線程體沒有執行完成的時候,主線程一直阻塞等待,執行完則直接返回結果。

 

package thread.test04;  
import java.util.concurrent.*;  
public class ThreadTestA {  
    public static void main(String[] args) {  
        ExecutorService e=Executors.newFixedThreadPool(10);  
        e.execute(new MyRunnableA());  
        e.execute(new MyRunnableB());  
       e.shutdown();  
   }  
  
}  
  
class MyRunnableA implements Runnable{  
      
    public void run(){  
        System.out.println("Runnable:run()....");  
        int i=0;  
        while(i<20){  
            i++;  
            for(int j=0;j<1000000;j++);  
            System.out.println("i="+i);  
        }  
    }  
}  
  
class MyRunnableB implements Runnable{  
    public void run(){  
        char c='A'-1;  
        while(c<'Z'){  
            c++;  
            for(int j=0;j<1000000;j++);  
            System.out.println("c="+c);  
        }  
    }  
}  
package thread.test04;  
  
import java.util.concurrent.Callable;  
import java.util.concurrent.ExecutionException;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Future;  
  
public class ThreadTestB {  
    public static void main(String[] args) {  
        ExecutorService e=Executors.newFixedThreadPool(10);  
        Future f1=e.submit(new MyCallableA());  
        Future f2=e.submit(new MyCallableA());  
        Future f3=e.submit(new MyCallableA());        
        System.out.println("--Future.get()....");  
        try {  
            System.out.println(f1.get());  
            System.out.println(f2.get());  
            System.out.println(f3.get());            
        } catch (InterruptedException e1) {  
            e1.printStackTrace();  
        } catch (ExecutionException e1) {  
            e1.printStackTrace();  
        }  
          
        e.shutdown();  
          
    }  
  
}  
  
class MyCallableA implements Callable<String>{  
    public String call() throws Exception {  
        System.out.println("開始執行Callable");  
        String[] ss={"zhangsan","lisi"};  
        long[] num=new long[2];  
        for(int i=0;i<1000000;i++){  
            num[(int)(Math.random()*2)]++;  
        }  
          
        if(num[0]>num[1]){  
            return ss[0];  
        }else if(num[0]<num[1]){  
            throw new Exception("棄權!");  
        }else{  
            return ss[1];  
        }  
    }  
      
}  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM