2013-05-31 37 views
4

後的JDK 7 Java文檔提出以下兩個成語來創建Java線程:設置一個Java線程的Runnable的建設

  1. 擴展Thread和覆蓋run()的

    class PrimeThread extends Thread { 
    long minPrime; 
    PrimeThread(long minPrime) { 
        this.minPrime = minPrime; 
    } 
    
    public void run() { 
        // compute primes larger than minPrime 
         . . . 
    } 
    } 
    
    ... 
    
    //And to launch the custom Thread 
    
    PrimeThread p = new PrimeThread(143); 
    
    p.start(); 
    
  2. 實現Runnable和創建一個將Runnable impl傳入其構造函數的新線程

    class PrimeRun implements Runnable { 
    long minPrime; 
    PrimeRun(long minPrime) { 
        this.minPrime = minPrime; 
    } 
    
    public void run() { 
        // compute primes larger than minPrime 
         . . . 
    } 
    } 
    
    ... 
    
    //And to launch a new Thread with this Runnable's behavior 
    
    PrimeRun p = new PrimeRun(143); 
    
    new Thread(p).start(); 
    

這些都很好,但我希望能夠創建Thread的子類,然後在稍後的某個時間定義並設置其Runnable實現(例如,不只是在線程的構造函數中)。從我可以告訴,Java的Thread類並沒有提供實現這個的手段,所以我想出了以下內容:

public class FlexiThread extends Thread{ 


//The Runnable impl to be executed 
private Runnable mvRunner; 

//Construct an empty subclass of Thread 
public FlexiThread(){ 
    super(); 

} 

//Construct a subclass of Thread which provides 
//its Runnable impl immediately 
public FlexiThread(Runnable r){ 
    super(r); 
    mvRunner = r; 

} 

/** 
* 
* @return -- the Runnable implementation whose 
* run() method will be invoked when this thread 
* is started 
*/ 
public Runnable getRunnableToExecute(){ 
    return mvRunner; 
} 
/** 
* @param runner -- the Runnable implementation whose 
* run() method will be invoked when this thread 
* is started 
*/ 
public void setRunnableToExecute(Runnable runner){ 
    mvRunner = runner; 
} 


@Override 
public void run(){ 
    mvRunner.run(); 
} 

} 

我測試FlexiThread,它似乎按預期方式工作(它執行我給的任何代碼至少在Android ICS和JB上,Runnable impl的run方法在通過DDMS驗證的獨立執行線程中);使用上面給出的FlexiThread策略有沒有什麼錯誤/潛在危險/效率低下?如果是這樣,在構建Thread子類的Runnable之後定義一個更好的方法是什麼?

+0

爲什麼要擴展'Thread'?爲什麼你不能只擴展'Runnable'? – Xeon

+1

您的靈活和慣用的舊方式之間的真正區別是什麼?無論如何你需要在調用'start()'之前設置runnable。 –

+0

AFAIK Android僅支持Java 6. –

回答

7

,因爲這是可重複使用的和可控的,我會用一個Executor。

ExecutorService es = Executors.newSingleThreadedPool(); 

// set a runnable later. 
es.submit(new MyRunnable()); 

// give it another runnable when that finishes. 
es.submit(new MyRunnable2()); 

// don't need it any more 
es.shutdown(); 
+0

+1是的,這是正確的答案。 – Gray

+0

@格雷乾杯... –

2

有什麼不對/潛在危險/低效以上

給出的FlexiThread戰略

我說沒有,這很好,雖然看起來危險的我,構建一個線程,不能直到後來纔開始。當然,你應該添加一些很好的代碼評論來解釋發生了什麼。如果尚未設置mvRunner,當您嘗試啓動線程時,我還會添加一些帶有良好消息的拋出。

一個改進是延長線,但創建一個FlexiRunnable代替:

public class FlexiRunnable implements Runnable { 
    private Runnable delegate; 
    private volatile boolean running = false; 
    public void run() { 
     running = true; 
     if (delegate != null) { 
      delegate.run(); 
     } 
    } 
    public void setDelegate(Runnable delegate) { 
     if (running) { 
      throw new IllegateStateException("The thread is already running..."); 
     } 
     this.delegate = delegate; 
    } 
} 

... 
FlexiRunnable flexi = new FlexiRunnable(); 
Thread thread = new Thread(flexi); 
... 
flexi.setDelegate(...); 
thread.start(); 
+1

如何使用'Executors'? – Fildor

+0

是的,你是對的@Fildor。彼得的回答是正確的。 – Gray