Java线程池饱和策略

最近在看 Java并发编程的艺术一书,第9章提到了线程池的实现原理,其中有这么一句话:
线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

那我们就来说说这个饱和策略是怎么一回事。
Java线程池会将提交的任务先置于工作队列中,在从工作队列中获取(阻塞队列直接由生产者提交给工作线程)。那么工作队列就有两种实现策略:无界队列和有界队列。无界队列不存在饱和的问题,但是其问题是当请求持续高负载的话,任务会无脑的加入工作队列,那么很可能导致内存等资源溢出或者耗尽。而有界队列不会带来高负载导致的内存耗尽的问题,但是有引发工作队列已满情况下,新提交的任务如何管理的难题,这就是线程池工作队列饱和策略要解决的问题。

饱和策略分为:Abort 策略, CallerRuns 策略,Discard策略,DiscardOlds策略。

代码如下:

import java.util.concurrent.*;

public class Main {

    // 基本线程2个,最大线程3个,工作队列容量为5,饱和策略为 AbortPolicy
    ExecutorService exec = new ThreadPoolExecutor(2, 3, 0L, TimeUnit.SECONDS,
            new LinkedBlockingDeque<Runnable>(5), new ThreadPoolExecutor.AbortPolicy());
    private void putrunnable() {
        for (int i = 0; i < 10; i++) {
            exec.submit(new Task());
        }
        exec.shutdown();
    }

    static class Task implements Runnable {
        private static int count = 0;
        private int id = 0;
        public Task() {
            id = ++count;
        }
        @Override
        public void run() {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务" + id + ":" + Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {
        new Main().putrunnable();
    }

}

当工作队列满了,不同策略的处理方式为:

1、Abort策略:默认策略,新任务提交时直接抛出未检查的异常RejectedExecutionException,该异常可由调用者捕获。在之上的代码中已写。
运行结果:
这里写图片描述
程序抛出了RejectedExecutionException,并且一共运行了8个任务(线程池开始能运行3个任务,工作队列中存储5个队列)。当工作队列满了的时候,直接抛出了异常,而且JVM一直不退出。我们可以看到执行任务的线程全是线程池中的线程。

2、CallerRuns策略:为调节机制,既不抛弃任务也不抛出异常,而是将某些任务回退到调用者。不会在线程池的线程中执行新的任务,而是在调用exector的线程中运行新的任务。
运行结果:
这里写图片描述
所有的任务都被运行,且有2(10 - 3 -5)个任务是在main线程中执行成功的,8个任务在线程池中的线程执行的。也有可能main线程只执行一个,因为可能出现最后一个加入线程池的时候,第一个已经执行完毕。

3、Discard策略:新提交的任务被抛弃。
运行结果:
这里写图片描述
通过上面的结果可以显示:没有异常抛出,后面提交的2个新任务被抛弃,只处理了前8(3+5)个任务,JVM退出。

4、DiscardOldest策略:队列的是“队头”的任务,然后尝试提交新的任务。(不适合工作队列为优先队列场景)
运行结果:
这里写图片描述
一共运行8个任务,程序结束,后面添加的任务9,任务10被执行了,而前面的任务3,任务4被丢弃。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值