使用有界队列的线程池使用DiscardOldestPolicy拒绝策略

本文详细介绍了如何在Java中使用有界队列的线程池,并探讨了当任务达到队列上限时,应用DiscardOldestPolicy拒绝策略的原理和效果。通过这种方式,线程池能够优雅地处理过载情况,丢弃最旧的任务来为新任务腾出空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class MyTask implements Runnable {

    private int taskId;
    private String taskName;

    public MyTask(int taskId, String taskName){
        this.taskId = taskId;
        this.taskName = taskName;
    }

    public int getTaskId() {
        return taskId;
    }

    public void setTaskId(int taskId) {
        this.taskId = taskId;
    }

    public String getTaskName() {
        return taskName;
    }

    public void setTaskName(String taskName) {
        this.taskName = taskName;
    }

    @Override
    public void run() {
        try {
            System.out.println("run taskId =" + this.taskId);
            Thread.sleep(5*1000);
            //System.out.println("end taskId =" + this.taskId);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }       
    }

    public String toString(){
        return Integer.toString(this.taskId);
    }

}
*****************************************************

package com.bjsxt.height.concurrent018;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;



public class UseThreadPoolExecutor1 {


    public static void main(String[] args) {
        /**
         * 在使用有界队列时,若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,
         * 若大于corePoolSize,则会将任务加入队列,
         * 若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,
         * 若线程数大于maximumPoolSize,则执行拒绝策略。或其他自定义方式。
         * 
         */ 
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                1,              //coreSize
                2,              //MaxSize
                60,             //60
                TimeUnit.SECONDS, 
                new ArrayBlockingQueue<Runnable>(3)         //指定一种队列 (有界队列)
                //new LinkedBlockingQueue<Runnable>()
                //, new MyRejected()
                , new DiscardOldestPolicy()
                );

        MyTask mt1 = new MyTask(1, "任务1");
        MyTask mt2 = new MyTask(2, "任务2");
        MyTask mt3 = new MyTask(3, "任务3");
        MyTask mt4 = new MyTask(4, "任务4");
        MyTask mt5 = new MyTask(5, "任务5");
        MyTask mt6 = new MyTask(6, "任务6");

        pool.execute(mt1);
        pool.execute(mt2);
        pool.execute(mt3);
        pool.execute(mt4);
        pool.execute(mt5);
        pool.execute(mt6);

        pool.shutdown();

    }
}
运行结果:
run taskId =5
run taskId =1
run taskId =3
run taskId =4
run taskId =6

分析:
使用有界阻塞队列,先为1开启一个核心线程,然后为2 3 4入队,然后
为5开启一个线程(最大线程),本来应该是舍弃6,但是指定了舍弃策略
是舍弃最老的,也就是阻塞队列队头元素2,所以舍弃2而执行6

如果自定义舍弃策略:
一般不要给用户浏览器反馈信息,因为此时系统负荷非常严重,如果此时要
拒绝10000个队列,系统根本没有这么多资源,所以实际项目中就是把taskID
记载到log日志中就可以了。

如果使用无界队列很简单,开启核心线程数,多余的全部阻塞直到内存耗尽。
如果使用有界队列,要清楚工作流程:
* 若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,
* 若大于corePoolSize,则会将任务加入队列,
* 若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,
* 若线程数大于maximumPoolSize,则执行拒绝策略。或其他自定义方式。
* 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值