[Java]線程池

來源:互聯網
上載者:User

標籤:ram   locking   取出   com   exe   eject   靈活   pool   execution   

在沒有看不論什麼代碼之前首先想一下線程池應該有哪幾部分:

  • 任務隊列
  • 線程

任務隊列非常好辦。直接用堵塞隊列就能夠了:BlockingQueue<Runnable> workQueue。而線程是用來運行任務的,那麼理所當然應該是不斷地從任務隊列中取出任務來運行,我們來看ThreadPoolExecutor中的Worker的實現:

private final class Worker implements Runnable {private final ReentrantLock runLock = new ReentrantLock();private Runnable firstTask;volatile long completedTasks;Thread thread;// 運行taskprivate void runTask(Runnable task) {final ReentrantLock runLock = this.runLock;runLock.lock();try {// 檢查線程池的狀態,推斷是否中斷if (runState < STOP && Thread.interrupted() && runState >= STOP)thread.interrupt();boolean ran = false;beforeExecute(thread, task);// 運行任務前的操作try {task.run(); // 任務開始運行ran = true;afterExecute(task, null);// 運行任務後的操作++completedTasks;} catch (RuntimeException ex) {if (!ran)afterExecute(task, ex);// 運行任務後的操作throw ex;}} finally {runLock.unlock();}}// 線程啟動之後開始運行public void run() {try {Runnable task = firstTask;firstTask = null;// 從線程池中取出Runnable然後運行while (task != null || (task = getTask()) != null) {runTask(task);task = null;}} finally {workerDone(this);}}}

通過推斷runLock是不是鎖上的狀態就能夠推斷Worker是否在運行任務了。當然getTask失敗的時候,Worker的任務也就結束了,我們有時候會希望線程去等一段時間,假設這段時間裡面沒有任務到達線程才退出。

這個在堵塞隊列中有線程的方法。在getTask能夠看到,例如以下:

r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);

在拿到任務的時候,假設如今線程池還非常小,那麼如今不須要將任務放到堵塞隊列裡面去,直接建立一個線程執行就能夠了。在這條路走不通的時候才會“繞彎路”來做。由於堵塞隊列也是有容量限制的,那麼在嘗試將任務放進去的時候可能會失敗。

假設讓我寫的話就不會嘗試了,而是直接調用堵塞方法讓主線程堵塞在這裡,這樣事實上並不好:

  • 不夠靈活
  • 調用的線程被堵塞了,浪費資源,事實上它是能夠用來運行任務的

假設自己要實現reject策略的話實現以下介面就能夠了:

public interface RejectedExecutionHandler {void rejectedExecution(Runnable r, ThreadPoolExecutor executor);}

有可能出現一種情況:插入任務之後線程池的狀態改變了。那麼也要保證該任務可以被處理(並不一定是任務被完畢。也可能是拒絕),那麼以下來看提交任務的完整邏輯:

public void execute(Runnable command) {if (command == null)throw new NullPointerException();// 嘗試建立線程並運行任務if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {// 嘗試將線程放入堵塞隊列if (runState == RUNNING && workQueue.offer(command)) {if (runState != RUNNING || poolSize == 0)// 確保任務會被處理ensureQueuedTaskHandled(command);} else if (!addIfUnderMaximumPoolSize(command))// 假設如今能建立一個線程運行該任務的話,就不要拒絕它了。。

。reject(command);}}

能夠發如今線程池執行期間改動各種閥值都是能夠起到作用的。假設在spring中想用簡單的線程池的話沒有必要自己寫一個,直接用現成的配置一個就能夠了,比方:

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"><property name="corePoolSize" value="5" /><property name="maxPoolSize" value="10" /><property name="queueCapacity" value="25" /></bean> 


---------- ---------- ---------- ---------- END ---------- ---------- ---------- ----------

[Java]線程池

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.