您的位置:首页 > 其它

ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭

2016-05-25 10:51 344 查看
ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭。 
但是我用了计数信号量Semaphore后,发现线程还没有跑完,他就执行了shutdown(). 

Java代码  


import java.util.concurrent.ExecutorService;  

import java.util.concurrent.Executors;  

import java.util.concurrent.Semaphore;  

  

public class SemaphoreTest extends Thread {  

    Semaphore position;  

    private int id;  

  

    public SemaphoreTest(int i, Semaphore s) {  

        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 Semap
10e85
horeTest(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;  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: