【JUC并发】黑马程序员:newFixedThreadPool(固定大小线程池的饥饿现象与解决办法)

newFixedThreadPool 介绍

  • 线程执行完不会结束
  • 核心线程数 == 最大线程数(没有救急线程被创建),因此也无需超时时间
  • 阻塞队列是无界的,可以放任意数量的任务

评价 适用于任务量已知,相对耗时的任务

饥饿问题引出

餐馆中的服务员负责 (点菜+上菜 )/ 做菜 ,点完菜需要等菜做好了然后上菜
代码逻辑:固定大小为 2 的线程池,两个线程池同时 (点菜+上菜 )。这时候都需要等待菜做好了然后上菜,而却没有足够线程去做菜

代码

    public static void main(String[] args) {
    	//菜单
        List<String> list= Arrays.asList("宫保鸡丁","青椒炒肉","西红柿炒鸡蛋");
        //固定大小为 2 的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        //利用同一个线程池执行任务
        executorService.execute(()->{
            log.debug("点菜"+list.get(new Random().nextInt(3)));
            log.debug("等菜做好...");
            利用同一个线程池执行任务
            Future<String> submit = executorService.submit(() -> {
                return "做好了";
            });
            //等待做好菜
            try {
                log.debug(submit.get()+",上菜!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        });
        //利用同一个线程池执行任务
        executorService.execute(()->{
            log.debug("点菜"+list.get(new Random().nextInt(3)));
            log.debug("等菜做好...");
            //利用同一个线程池执行任务
            Future<String> submit = executorService.submit(() -> {
                return "做好了";
            });
            //等待做好菜
            try {
                log.debug(submit.get()+"上菜");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        });
    }

输出

15:33:43 [pool-2-thread-1] c.eight-Demo4 - 点菜西红柿炒鸡蛋
15:33:43 [pool-2-thread-2] c.eight-Demo4 - 点菜青椒炒肉
15:33:43 [pool-2-thread-2] c.eight-Demo4 - 等菜做好...
15:33:43 [pool-2-thread-1] c.eight-Demo4 - 等菜做好...

饥饿问题解决

  • 增加线程池的大小,不过不是根本解决方案
  • 不同的任务类型,采用不同的线程池,如下代码

代码

    public static void main(String[] args) {
    	//菜单
        List<String> list= Arrays.asList("宫保鸡丁","青椒炒肉","西红柿炒鸡蛋");
        //固定大小为 2 的线程池 waiter 
        ExecutorService waiter = Executors.newFixedThreadPool(2);
        //固定大小为 2 的线程池 cook 
        ExecutorService cook = Executors.newFixedThreadPool(2);
        //利用线程池 waiter 执行任务
        waiter.execute(()->{
            log.debug("服务员点菜"+list.get(new Random().nextInt(3)));
            log.debug("服务员等菜做好...");
            //利用线程池 cook 执行任务
            Future<String> submit = cook.submit(() -> {
                log.debug("厨师做好菜了");
                return "true";
            });
            //等待线程池 cook 做好菜
            try {
                submit.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            log.debug("服务员上菜!");
        });
        //利用线程池 waiter 执行任务
        waiter.execute(()->{
            log.debug("服务员点菜"+list.get(new Random().nextInt(3)));
            log.debug("服务员等菜做好...");
            //利用线程池 cook 执行任务
            Future<String> submit = cook.submit(() -> {
                log.debug("厨师做好菜了");
                return "true";
            });
            //等待线程池 cook 做好菜
            try {
                submit.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            log.debug("服务员上菜!");
        });
    }

输出

15:38:14 [pool-2-thread-1] c.eight-Demo4 - 服务员点菜西红柿炒鸡蛋
15:38:14 [pool-2-thread-2] c.eight-Demo4 - 服务员点菜西红柿炒鸡蛋
15:38:14 [pool-2-thread-1] c.eight-Demo4 - 服务员等菜做好...
15:38:14 [pool-2-thread-2] c.eight-Demo4 - 服务员等菜做好...
15:38:14 [pool-3-thread-2] c.eight-Demo4 - 厨师做好菜了
15:38:14 [pool-3-thread-1] c.eight-Demo4 - 厨师做好菜了
15:38:14 [pool-2-thread-2] c.eight-Demo4 - 服务员上菜!
15:38:14 [pool-2-thread-1] c.eight-Demo4 - 服务员上菜!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愿你满腹经纶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值