【并发编程】- 线程池使用自定义拒绝策略

109 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情

线程池使用方法setRejectedExecutionHandler()和getRejectedExecutionHandler()

方法setRejectedExecutionHandler()和getRejectedExecutionHandler()的作用是可以处理任务被拒绝执行时的行为。

线程执行代码如下:

public class TheRunnable implements Runnable {

    private String username;

    public TheRunnable(String username){
        super();
        this.username=username;
    }

    public String getUsername(){
        return username;
    }

    public void setUsername(String username){
        this.username=username;
    }

    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() +" username= "+username+"  开始时间:"+System.currentTimeMillis());
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() +" username= "+username+"  结束时间:"+System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行类代码如下:

public class TheThreadPoolExecutorRun {
    public static void main(String[] args) {
        TheRunnable g1 = new TheRunnable("G1");
        TheRunnable g2 = new TheRunnable("G2");
        TheRunnable g3 = new TheRunnable("G3");
        TheRunnable g4 = new TheRunnable("G4");
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 999, TimeUnit.SECONDS, new SynchronousQueue<>());
        threadPoolExecutor.execute(g1);
        threadPoolExecutor.execute(g2);
        threadPoolExecutor.execute(g3);
        threadPoolExecutor.execute(g4);
    }
}

运行结果如下:

pool-1-thread-1 username= G1  开始时间:1655371520766
pool-1-thread-2 username= G2  开始时间:1655371520766
pool-1-thread-3 username= G3  开始时间:1655371520767
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.ozx.concurrentprogram.executor.service.TheRunnable@29444d75 rejected from java.util.concurrent.ThreadPoolExecutor@44e81672[Running, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
	at com.ozx.concurrentprogram.executor.controller.TheThreadPoolExecutorRun.main(TheThreadPoolExecutorRun.java:24)
pool-1-thread-3 username= G3  结束时间:1655371522781
pool-1-thread-1 username= G1  结束时间:1655371522781
pool-1-thread-2 username= G2  结束时间:1655371522782

从运行结果看出线程池使用SynchronousQueue队列,拒绝策略是拒绝运行多余的任务。

出现这种异常时可以自定义拒绝执行任务的操作

创建自定义拒绝拦截类代码如下:

public class TheRejectExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println(((TheRunnable)r).getUsername()+"被拒绝执行!");
    }
}

修改运行类代码

public class TheThreadPoolExecutorRun {
    public static void main(String[] args) {
        TheRunnable g1 = new TheRunnable("G1");
        TheRunnable g2 = new TheRunnable("G2");
        TheRunnable g3 = new TheRunnable("G3");
        TheRunnable g4 = new TheRunnable("G4");
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 999, TimeUnit.SECONDS, new SynchronousQueue<>());
        threadPoolExecutor.setRejectedExecutionHandler(new TheRejectExecutionHandler());
        threadPoolExecutor.execute(g1);
        threadPoolExecutor.execute(g2);
        threadPoolExecutor.execute(g3);
        threadPoolExecutor.execute(g4);
    }
}

运行结果如下:

G4被拒绝执行!
pool-1-thread-2 username= G2  开始时间:1655373362718
pool-1-thread-1 username= G1  开始时间:1655373362718
pool-1-thread-3 username= G3  开始时间:1655373362718
pool-1-thread-3 username= G3  结束时间:1655373364721
pool-1-thread-1 username= G1  结束时间:1655373364721
pool-1-thread-2 username= G2  结束时间:1655373364724

从运行结果看出被拒绝执行的任务日志化。