Callable,Runnable比較及用法

編寫多線程程序是爲了實現多任務的併發執行,從而可以更好地與用戶交互。對目前的java來講,通常有三種方法,Thread,Runnable,Callable. java

Runnable和Callable的區別是,
(1)Callable規定的方法是call(),Runnable規定的方法是run().
(2)Callable的任務執行後可返回值,而Runnable的任務是不能返回值得
(3)call方法能夠拋出異常,run方法不能夠
(4)運行Callable任務能夠拿到一個Future對象,表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並檢索計算的結果。經過Future對象能夠了解任務執行狀況,可取消任務的執行,還可獲取執行結果。 多線程

一、經過實現Runnable接口來建立Thread線程: 併發

  步驟1:建立實現Runnable接口的類: 異步

         
class SomeRunnable implements Runnable
{
    public void run()
    {
      //do something here
    }
} 性能

步驟2:建立一個類對象: spa

       Runnable oneRunnable = new SomeRunnable(); 線程

步驟3:由Runnable建立一個Thread對象: code

       Thread oneThread = new Thread(oneRunnable); 對象

步驟4:啓動線程: blog

        oneThread.start();

至此,一個線程就建立完成了。

註釋:線程的執行流程很簡單,當執行代碼oneThread.start();時,就會執行oneRunnable對象中的void run();方法,

該方法執行完成後,線程就消亡了。

二、與方法1相似,經過實現Callable接口來建立Thread線程:其中,Callable接口(也只有一個方法)定義以下:

public interface Callable<V>   
{   
    V call() throws Exception;   

步驟1:建立實現Callable接口的類SomeCallable<Integer>(略);

步驟2:建立一個類對象:

      Callable<Integer> oneCallable = new SomeCallable<Integer>();

步驟3:由Callable<Integer>建立一個FutureTask<Integer>對象:

      FutureTask<Integer> oneTask = new FutureTask<Integer>(oneCallable);

      註釋:FutureTask<Integer>是一個包裝器,它經過接受Callable<Integer>來建立,它同時實現了Future和Runnable接口。
步驟4:由FutureTask<Integer>建立一個Thread對象:

       Thread oneThread = new Thread(oneTask);

步驟5:啓動線程:

       oneThread.start();

至此,一個線程就建立完成了。

三、經過繼承Thread類來建立一個線程:

步驟1:定義一個繼承Thread類的子類:

       

class SomeThead extends Thraad
{
    public void run()
    {
     //do something here
    }
}

步驟2:構造子類的一個對象:

      SomeThread oneThread = new SomeThread();

步驟3:啓動線程:

      oneThread.start();

至此,一個線程就建立完成了。

       註釋:這種建立線程的方法不夠好,主要是由於其涉及運行機制問題,影響程序性能。

四、經過線程池來建立線程:

步驟1:建立線程池:

      ExecutorService pool = Executors.newCachedThreadPool();

步驟2:經過Runnable對象或Callable對象將任務提交給ExecutorService對象:

      Future<Integer> submit(Callable<Integer> task);

      註釋:Future是一個接口,它的定義以下:

               
public interface Future<T>
{
    V get() throws ...;
    V get(long timeout, TimeUnit unit) throws ...;
    void cancle(boolean mayInterrupt);
    boolean isCancelled();
    boolean isDone();
}

      至此,一個線程就建立完成了。

      註釋:線程池需調用shutdown();方法來關閉線程。

五、經過事件分配線程直接使用程序中的原有線程:

使用方法:
直接調用EventQueue類的靜態方法invokeLater():

      EventQueue.invokeLater(oneRunnable);

      註釋:調用EventQueue.invokeLater(oneRunnable);會直接執行oneRunnable對象中的run()方法


相關實例:

public class CallableFutureTest { public static void main(String[] args) throws InterruptedException, ExecutionException {  
        System.out.println("start main thread"); 
        final ExecutorService exec = Executors.newFixedThreadPool(5);  


        Callable<String> call = new Callable<String>() { public String call() throws Exception {  
                System.out.println(" start new thread.");  
                Thread.sleep(1000 * 5);  
                System.out.println(" end new thread."); // call方法返回值 
 return "some value.";  
            }  
        };  
        Future<String> task = exec.submit(call);  
        Thread.sleep(1000 * 2); // 阻塞當前線程,即主線程,並等待子線程結束  
 task.get(); 
        exec.shutdown();  
        System.out.println("end main thread");  
    }  
}
相關文章
相關標籤/搜索