【并发编程】- 线程池使用CallerRunsPolicy策略

594 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

CallerRunsPolicy策略

CallerRunsPolicy策略是当任务添加到线程池中被拒绝时,会使用调用线程池的Thread线程对象处理被拒绝的任务。

执行代码如下:

public class FirstRunnable implements Runnable {

    @Override
    public void run() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        try {
            Thread.sleep(5000);
            System.out.println(Thread.currentThread().getName() +"  结束时间:"+simpleDateFormat.format(new Date()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行类执行代码如下:

@Slf4j
public class CallerRunsPolicyRun {
    public static void main(String[] args) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        FirstRunnable firstRunnable = new FirstRunnable();
        LinkedBlockingDeque<Runnable> deque = new LinkedBlockingDeque<>(2);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 5, TimeUnit.SECONDS, deque, new ThreadPoolExecutor.CallerRunsPolicy());
        log.info("线程名:{},开始执行时间:{}",Thread.currentThread().getName(),simpleDateFormat.format(new Date()));
        for (int i = 0; i < 4 ; i++) {
            threadPoolExecutor.submit(firstRunnable);
        }
        log.info("线程名:{},执行结束时间:{}",Thread.currentThread().getName(),simpleDateFormat.format(new Date()));
    }
}

运行结果如下:

10:48:26.001 [main] INFO com.ozx.concurrentprogram.executor.controller.CallerRunsPolicyRun - 线程名:main,开始执行时间:10:48:25

10:48:26.061 [main] INFO com.ozx.concurrentprogram.executor.controller.CallerRunsPolicyRun - 线程名:main,执行结束时间:10:48:26

pool-1-thread-1 结束时间:10:48:31

pool-1-thread-2 结束时间:10:48:31

pool-1-thread-1 结束时间:10:48:36

pool-1-thread-2 结束时间:10:48:36

从运行结果看出,线程main被阻塞,严重影响程序的运行效率,所以并不建议这样做,可以通过改变的代码结果可以改善这种情况。

添加一个线程执行代码如下:

@Slf4j
public class SecondRunnable implements Runnable {
    @Override
    public void run() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        FirstRunnable firstRunnable = new FirstRunnable();
        LinkedBlockingDeque<Runnable> deque = new LinkedBlockingDeque<>(2);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 5, TimeUnit.SECONDS, deque, new ThreadPoolExecutor.CallerRunsPolicy());
        log.info("线程名:{},开始执行时间:{}",Thread.currentThread().getName(),simpleDateFormat.format(new Date()));
        for (int i = 0; i < 4 ; i++) {
            threadPoolExecutor.submit(firstRunnable);
        }
        log.info("线程名:{},执行结束时间:{}",Thread.currentThread().getName(),simpleDateFormat.format(new Date()));
    }
}

运行类执行代码如下:

@Slf4j
public class CallerRunsPolicyRunn {
    public static void main(String[] args) {
        SecondRunnable secondRunnable = new SecondRunnable();
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.submit(secondRunnable);
        log.info("main主线程结束!");
    }
}

运行结果如下:

11:26:04.921 [pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.service.SecondRunnable - 线程名:pool-1-thread-1,开始执行时间:11:26:04

11:26:04.919 [main] INFO com.ozx.concurrentprogram.executor.controller.CallerRunsPolicyRuunable - main主线程结束!

11:26:04.927 [pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.service.SecondRunnable - 线程名:pool-1-thread-1,执行结束时间:11:26:04

pool-2-thread-2 结束时间:11:26:09

pool-2-thread-1 结束时间:11:26:09

pool-2-thread-2 结束时间:11:26:14

pool-2-thread-1 结束时间:11:26:14

从运行结果看出线程main并未被阻塞。