2012-10-06 30 views
5

我需要問一下如何在發生任務提交時每次執行線程數量不變時執行線程池。使用任何隊列IMPL(在執行人避免每次線程的創建和刪除的開銷)我們如何在Java中執行下一個任務後保存下一個任務(線程池實現)

executor.submit(Runnable) 

假設我們在開始創建一些線程和任務時,我們來分配任務給他們(線程)。但在完成後的任務怎麼可能一個線程返回到其池時再爲每個線程的生命週期中說,

「它的run方法執行後它進入終止狀態,不能再使用」

我不明白線程池是如何工作的,以便有恆定數量的線程執行任何任務到其隊列。

如果有人能夠在任務完成後爲我提供一個線程重用的例子,那將會很棒。

!!在此先感謝。

+0

概念上它很容易。您啓動一個固定數量的運行方法在隊列中等待的隊列。您將工作請求發送到隊列,運行方法將請求解除隊列並執行工作請求。然後他們又回到隊列中等待。訣竅是找到正確類型的隊列--JDK中有六個,但只有一個特殊的(最後我看了)適合這個,它隱藏在一個角落裏。 –

回答

2

「它的run方法執行後它進入終止狀態,不能再使用」

它沒有完成其run()相反,它擁有可運行運行的循環()你提供的任務。


顯着簡化線程池模式,你看起來像這樣的代碼。

final BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<Runnable>(); 

public void submit(Runnable runs) { 
    tasks.add(runs); 
} 

volatile boolean running = true; 

// running in each thread in the pool 
class RunsRunnable implement Runnable { 
    public void run() { 
     while(running) { 
      Runnable runs = tasks.take(); 
      try { 
       runs.run(); 
      } catch(Throwable t) { 
       // handles t 
      } 
     } 
    } 
} 

在這個例子中,你可以看到,雖然run()的線程中的每個任務完成後,運行()本身並不直到池是關機。

+0

但是如果我們直接執行run方法,那麼沒有線程會產生,它只會執行這個方法。那麼它是否意味着執行(在自定義impl中)可以接受任何具有相同合約的任務(如Runnable已經運行()),我們必須在池線程中調用該合約方法。沒有使用Runnable或Callable作爲任務? – Virendra

+0

我已經添加了一個例子。我認爲你假設當Runtime.run()返回時,當它只是一個方法調用時會發生一些特殊情況。當沒有其他任何事情時,線程停止。 BTW UncaughtExceptionHandler可以在run()退出後調用,以便線程不會立即終止。 –

0

你可以看看這裏:http://www.ibm.com/developerworks/library/j-jtp0730/index.html瞭解更多細節和實施例。如果隊列爲空,則池中的線程將等待,並且一旦收到隊列中有某些元素的通知,它們將分別啓動合適的消息。

+0

同樣的問題在這裏。爲什麼當他們只用於調用他們的合同方法時,有必要將任務設置爲Runnable或Callable。 r =(Runnable)queue.removeFirst(); r.run(); 是否有必要只有Runnable。我們可以對任何其他運行方法的對象進行分析。因爲它的最終目標是使用不超過該線程的線程來調用? – Virendra

0

ExecutorService executor = Executors.newFixedThreadPool(2);

-上述語句創建的線程池具有2

executor.execute(new Worker());

固定大小 -上述語句採用類工人已實現Runnable的一個實例接口。

-現在這裏Executors是一箇中間對象,執行任務。它管理線程對象。

-通過執行上面的語句run()方法將被執行,而一旦run()方法完成後,線程亙古進入死亡狀態,但移動放回池中,等待有另一個工作分配所以它可以再次進入Runnable狀態,然後運行,所有這些都由Executors處理。

executor.shutdown();

-上面的語句將關閉執行人本身,適當地處理其管理的所有線程的關機.. shutdown()該中心對象,這反過來又可以終止每個註冊執行人對。

////////// Edited Part////////////////////// 

- 所有可運行的首先有一個run()方法,該方法不能返回任何東西,和run()方法不能拋出checked異常,因此可贖回在Java 5中,這是參數化類型的介紹,並有一個名爲call()的方法,它能夠返回並拋出Checked異常。

現在看到這個例子:

Thread t = new Thread(new Worker()); 

t.run(); 

t.start(); 

-t.run()僅僅是run()方法的簡單的通話,這不會跨越一個thread of execution

-t.start()而準備的東西爲thread of executioninitialization重要,然後電話run()方法Runnable,然後分配Task新成立的thread of execution快速返回....

使用Swing和時,Java中的線程成爲必需。 主要是GUI組件

+0

@Vivek可以請你回答我在下面的問題中提出的問題。爲什麼任務爲Runnable或Callable。我可以給它任何有run()方法的obj。因爲pooling線程只調用run()而不是從它創建任何線程。那麼實際上不需要Runnable? – Virendra

+0

@Virendra請看我的編輯答案..... –

+0

所以在執行器的情況下,t.run()正在工作,因爲我們在執行任務時不會創建任何t.start()調用。因此,這與提供任何可能不是Ru​​nnable實現的任務相同,但它具有run()方法。作爲Executor的PoolWorker只執行run方法(如t.run())在任務中不使用線程質量? – Virendra

0

我完全同意彼得,但想要添加與ExecutorService執行流程相關的步驟,以便清楚理解。

  • 如果你創建的線程池(固定大小的池)並不意味着創建線程。
  • 如果提交和/或執行新的任務(RunnubleCallable)新的線程將被創建伸出如果創建的線程<大小池的
  • 創建的線程不返回到池的數量,線程可以阻塞等待新的價值隊列,這一點我們可以調用返回到池
  • 所有線程池執行像像上面描述的彼得。
1

通常當我們使用線程池時會發生什麼,它的內部Run方法被迫迭代運行。直到隊列中有可用的任務。

在下面的例子中,pool.removeFromQueue()將迭代運行。

public class MyThread<V> extends Thread { 
    private MyThreadPool<V> pool; 
    private boolean active = true; 

    public boolean isActive() { 
     return active; 
    } 

    public void setPool(MyThreadPool<V> p) { 
     pool = p; 
    } 

    /** 
    * Checks if there are any unfinished tasks left. if there are , then runs 
    * the task and call back with output on resultListner Waits if there are no 
    * tasks available to run If shutDown is called on MyThreadPool, all waiting 
    * threads will exit and all running threads will exit after finishing the 
    * task 
    */ 
    @Override 
    public void run() { 
     ResultListener<V> result = pool.getResultListener(); 
     Callable<V> task; 
     while (true) { 
      task = pool.removeFromQueue(); 
      if (task != null) { 
       try { 
        V output = task.call(); 
        result.finish(output); 
       } catch (Exception e) { 
        result.error(e); 
       } 
      } else { 
       if (!isActive()) 
        break; 
       else { 
        synchronized (pool.getWaitLock()) { 
         try { 
          pool.getWaitLock().wait(); 
         } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
        } 
       } 
      } 
     } 
    } 

    void shutdown() { 
     active = false; 
    } 

需要設計你的線程池

public MyThreadPool(int size, ResultListener<V> myResultListener) { 
     tasks = new LinkedList<Callable<V>>(); 
     threads = new LinkedList<MyThread<V>>(); 
     shutDown = false; 
     resultListener = myResultListener; 
     for (int i = 0; i < size; i++) { 
      MyThread<V> myThread = new MyThread<V>(); 
      myThread.setPool(this); 
      threads.add(myThread); 
      myThread.start(); 
     } 
    } 
相關問題