ExecutorService.shutdown()應該是線上程執行完畢後,才會去關閉
阿新 • • 發佈:2018-11-22
ExecutorService.shutdown()應該是線上程執行完畢後,才會去關閉。
但是我用了計數訊號量Semaphore後,發現執行緒還沒有跑完,他就執行了shutdown().
Java程式碼
PS:
1、程式碼中主執行緒並沒有等待執行緒池執行完畢這一說,而是持續往下執行
2、至於訊號量,只會在幾個子執行緒之間發揮作用
3、主執行緒和執行緒池之間沒有直接關係,執行緒池使用自己的執行緒。生命週期也相互獨立。
4、shutdown()可以理解為:主執行緒要求執行緒池關閉,但不會為此等待執行緒池執行完畢。
5、實際發揮了等待作用的並不是執行緒池所提供的能力(當然執行緒池也確實提供了這類能力),而是:position.acquireUninterruptibly(2) 這句話。
shutdown() 作為函式,當然是立即執行,也即是不再接受新任務了;但是它即不會強行終止正在執行的任務,也不會取消已經提交的任務。也就是說之前提交的5個任務,仍然會執行完畢,且跟主執行緒生命週期無關,也就是即便你直接在後面寫上: if (1==1) return; 來立即結束主函式,你也會發現執行緒池的5個任務會順利執行完畢。
6、另一個長得很像的函式是:
shutdownNow(),這個函式比shutdown()更狠,兩點:
1)、對於尚未執行的任務,全部取消掉;
2)、對於正在執行的任務,發出interrupt()。
不過程式因為在發生異常時沒有正確釋放訊號量(應該放在finally塊中釋放),所以如果改為shutdownNow()會出問題:主執行緒死等。
Java5 併發學習
ExecutorService中submit和execute的區別
Java程式碼
但是我用了計數訊號量Semaphore後,發現執行緒還沒有跑完,他就執行了shutdown().
Java程式碼
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import
- public class SemaphoreTest extends Thread {
- Semaphore position;
- private int id;
- public
- this.id = i;
- this.position = s;
- }
-
- public void run() {
- try {
- if (position.availablePermits() > 0) {
- System.out.println("顧客[" + id + "]進入廁所,有空位");
- } else {
- System.out.println("顧客[" + id + "]進入廁所,沒空位,排隊");
- }
- position.acquire();
- System.out.println("【" + id + "】acquire坑位");
- Thread.sleep((int) (Math.random() * 1000));
- System.out.println("【" + id + "】完畢release");
- position.release();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String args[]) {
- ExecutorService pool = Executors.newCachedThreadPool();
- Semaphore position = new Semaphore(2); // 初始化兩個空位
- for (int i = 0; i < 5; i++) {
- pool.submit(new SemaphoreTest(i, position));
- }
- System.out.println("開始釋放執行緒池資源");
- pool.shutdown();
- System.out.println("完成釋放執行緒池資源");
- position.acquireUninterruptibly(2);
- System.out.println("如廁完畢,清理廁所");
- position.release(2);
- }
- }
PS:
1、程式碼中主執行緒並沒有等待執行緒池執行完畢這一說,而是持續往下執行
2、至於訊號量,只會在幾個子執行緒之間發揮作用
3、主執行緒和執行緒池之間沒有直接關係,執行緒池使用自己的執行緒。生命週期也相互獨立。
4、shutdown()可以理解為:主執行緒要求執行緒池關閉,但不會為此等待執行緒池執行完畢。
5、實際發揮了等待作用的並不是執行緒池所提供的能力(當然執行緒池也確實提供了這類能力),而是:position.acquireUninterruptibly(2) 這句話。
shutdown() 作為函式,當然是立即執行,也即是不再接受新任務了;但是它即不會強行終止正在執行的任務,也不會取消已經提交的任務。也就是說之前提交的5個任務,仍然會執行完畢,且跟主執行緒生命週期無關,也就是即便你直接在後面寫上: if (1==1) return; 來立即結束主函式,你也會發現執行緒池的5個任務會順利執行完畢。
6、另一個長得很像的函式是:
shutdownNow(),這個函式比shutdown()更狠,兩點:
1)、對於尚未執行的任務,全部取消掉;
2)、對於正在執行的任務,發出interrupt()。
不過程式因為在發生異常時沒有正確釋放訊號量(應該放在finally塊中釋放),所以如果改為shutdownNow()會出問題:主執行緒死等。
Java5 併發學習
ExecutorService中submit和execute的區別
Java程式碼
- public List<DrugDpInfoVO> selectRecipeSumVO(final AlertMessageKeyword query, PageBreaker page, final Integer engineRunFlag) {
- List<DrugDpInfoVO> list = optAlertmessageStatisticMapper.selectRecipeSumVO(this.getBaseDBName(), query, page, engineRunFlag);
- if (null == list || list.isEmpty()) {
- log.warn("無匹配記錄");
- return list;
- }
- //ExecutorService EXECUTORSERVICE = Executors.newFixedThreadPool(50);
- List<Future<DrugDpInfoVO>> listFuture = new ArrayList<>();
- try {
- for (final DrugDpInfoVO e : list) {
- Future<DrugDpInfoVO> future = EXECUTORSERVICE.submit(new Callable<DrugDpInfoVO>() {
- @Override
- public DrugDpInfoVO call() throws Exception {
- DrugDpInfoVO drugDpInfoVO = optAlertmessageStatisticMapper.selectSingleRecipeSumVO(getBaseDBName(), query, e, engineRunFlag);
- drugDpInfoVO.setAmount(e.getAmount());
- return drugDpInfoVO;
- }
- });
- listFuture.add(future);
- }
- list.clear();
- for (Future<DrugDpInfoVO> future : listFuture) {
- list.add(future.get());
- }
- } catch (Exception e) {
- log.error(e.getMessage(), e);
- }
- return list;
- }