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

130 阅读2分钟

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

自定义拒绝策略RejectedExecutionHandler接口的使用

自定义拒绝策略类代码如下:

@Slf4j
public class TheRejectedExecutionHandler implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        log.info("线程名:{} 被拒绝",((FutureTask)r).toString());
            }
}

线程执行代码如下:

@Slf4j
public class TheRunnable implements Runnable {

    private String username;

    public String getUsername() {
        return username;
    }

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

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



    @Override
    public void run() {
            log.info("线程名:{} 在运行",username);
    }
}

运行类代码如下:

public class RejectedExecutionHandlerRun {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService;
        threadPoolExecutor.setRejectedExecutionHandler(new TheRejectedExecutionHandler());
        threadPoolExecutor.submit(new TheRunnable("G1"));
        threadPoolExecutor.submit(new TheRunnable("G2"));
        threadPoolExecutor.submit(new TheRunnable("G3"));
        threadPoolExecutor.shutdown();
        threadPoolExecutor.submit(new TheRunnable("G4"));
    }
}

运行结果如下:

15:05:34.037 [pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G1 在运行 15:05:34.037 [pool-1-thread-2] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G2 在运行 15:05:34.037 [pool-1-thread-3] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G3 在运行 15:05:34.037 [main] INFO com.ozx.concurrentprogram.executor.handler.TheRejectedExecutionHandler - 线程名:java.util.concurrent.FutureTask@553f17c 被拒绝

从运行结果看出线程池调用自定义拒绝策略,接口RejectedExecutionHandler的主要作用是当线程池关闭后依然有任务要执行时,可以实现一些处理。

方法execute()与submit()的区别

execute()与submit()的区别如下:

  • 方法execute()没有返回值,而submit()方法可以有返回值。
  • 方法execute()在默认情况下异常直接抛出,不能捕获,但可以通过自定义ThreadFactory的方式进行捕获,而submit()方法在默认的情况下,可以catch Execution Exception 捕获异常。
  1. 关于有无返回值

    运行类代码如下:

    @Slf4j
    public class ExecuteOrSubmitRun {
        public static void main(String[] args) {
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("线程池执行了execute()方法,Runnable没有返回值!");
                }
            });
    
            Future<String> future = threadPoolExecutor.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    log.info("线程池执行了submit()方法,Callable有返回值!");
                    return String.valueOf(System.currentTimeMillis());
                }
            });
    
            try {
                log.info("Callable返回值:{}",future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    

    运行结果如下:

    15:32:33.528 [pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.controller.ExecuteOrSubmitRun - 线程池执行了execute()方法,Runnable没有返回值!

    15:32:33.573 [pool-1-thread-2] INFO com.ozx.concurrentprogram.executor.controller.ExecuteOrSubmitRun - 线程池执行了submit()方法,Callable有返回值!

    15:32:33.573 [main] INFO com.ozx.concurrentprogram.executor.controller.ExecuteOrSubmitRun - Callable返回值:1659943953573

    从运行结果看出,execute()没有返回值,而submit()方法具有返回值的功能。