记一次异步编程类CompletableFuture使用案例

  • CompletableFuture 是jdk8进入的一个异步变成工具,可以实现多线程编程。

  • 下面记录了一次,多线程处理处理一个业务的例子,并且要等待所有异步子线程执行完成后,主线程才能继续往下执行。

  • supplyAsync:异步线程有返回值; runAsync:异步线程没返回值

  • new ThreadPoolExecutor()的各个参数的意义:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {}
corePoolSize:核心线程数。会一直存活,及时没有任务需要执行,除非设置允许核心线程超时的参数。
maximumPoolSize:最大线程数。线程池中允许的最大线程,包含核心线程数。如果请求的线程数大于最大线程数,则会放到阻塞队列中。
keepAliveTime:非核心线程空闲等待时间,超过这个时间没有任务的话,非核心线程会被从线程池中销毁。如果设置为0L的话,则非核心线程执行完任务后如果没有任务的话会立即销毁。
unit:keepAliveTime的时间单位。
workQueue:表示缓存队列。当请求的线程数大于maximumPoolSize时,线程进入 BlockingQueue阻塞队列。
后续示例代码中使用的LinkedBlockingQueue是单向链表,使用锁来控制入队和出队的原子性,两个锁分别控制元素的添加和获取,是一个生产消费模型队列。
threadFactory:表示线程工厂。它用来生产一组相同任务的线程。定义了线程名称。
handler:拒绝策略, 是当任务队列满了,线程池线程数也达到最大了,这个时候,又有任务要执行的时候,执行什么策略进行处理这些任务。有四种策略
(1)AbortPolicy: 中止策略(默认) 直接抛出RejectedExecutionException异常

(2) DiscardPolicy: 丢弃策略 啥都不做,直接丢掉这个任务

(3) DiscardOldestPolicy: 丢弃最早的未处理的任务策略 会丢掉最早未执行的任务,然后重试当前这个任务

(4) CallerRunsPolicy: 调用者执行策略 如果executor没有关闭,会在执行execute方法的线程中直接调用任务的run方法。如果executor关闭了,这个任务就会被丢弃不执行。

一些总结:
线程池一般建议设置为全局的,不要定义到方法内部,这样会出现很多问题也失去了线程池中线程复用的初心。这样一来如何规划线程池的使用很重要,一般会按照同一个业务模块内的使用同一个线程池。并且这样全局的线程池是不shutdown()的。
这样的话核心线程数corePoolSize一定要定义好,因为核心线程数是会一直存在池中的。

线程池不定义在方法内部,如果非得写也不要忘了shutdown();否则上线后并发高了每个线程都创建线程池一定会出问题。

@RestController
@RequestMapping(value = "/test")
public class ThreadController {
@Autowired
TaskService taskService;
private static final ExecutorService pool;

    static {
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setNameFormat("export-pool-%d") //线程名称
                .build();
        pool = new ThreadPoolExecutor(
                4,
                10,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(2048),
                threadFactory,
                new ThreadPoolExecutor.AbortPolicy());
    }
    
public void test() throws ExecutionException, InterruptedException {
        List<CompletableFuture<String>> futrueList = new ArrayList<>();
        for (int i = 0; i<10;i++){
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                String s = null;
                try {
                    s = taskService.testThread("");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("标记0:"+Thread.currentThread().getName());
                return s;
            }, pool);

            futrueList.add(future);
        }
        System.out.println("标记1:"+Thread.currentThread().getName());
        CompletableFuture.allOf(futrueList.toArray(new CompletableFuture[futrueList.size()])).join(); // 等待所有子线程的任务执行完毕
        System.out.println("标记2:"+Thread.currentThread().getName());
        for (CompletableFuture<String> fu : futrueList) {
            System.out.println(fu.get());
        }
    }

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值