
CompletableFuture.runAsync的多线程下异步操作
🧰业务使用场景
CompletableFuture.runAsync()方法是Java中用于创建异步任务的工具,它可以在后台线程中执行指定的任务,并且可以在任务完成后返回结果或执行后续操作。这种方式可以实现多线程下的异步操作。
在多线程环境下,使用CompletableFuture.runAsync()可以实现并发执行多个任务,提高程序的性能和效率。每个异步任务都会在独立的线程中执行,互不影响,从而可以充分利用多核处理器的性能。
❗需要注意的点
在使用CompletableFuture.runAsync()方法创建异步任务时,需要注意以下几个问题:
- 共享变量的线程安全性:如果异步任务需要访问或修改共享的变量,需要确保对这些变量的访问是线程安全的。可以使用Atomic类、synchronized关键字、Lock等方式来保证共享变量的线程安全性。
- 变量的可见性:在多线程环境下,不同线程对同一个变量的修改可能不会立即对其他线程可见。可以使用volatile关键字来保证变量的可见性,或者通过CompletableFuture的一些方法来确保任务之间的数据传递和可见性。
- 避免数据竞争:在多线程环境下,可能会出现数据竞争的情况,即多个线程对同一变量进行读写操作,导致数据不一致。需要谨慎设计并发操作,避免数据竞争问题的发生。
- 异常处理:异步任务可能会抛出异常,需要在适当的地方捕获和处理异常,以避免程序崩溃或出现未知错误。
- 线程池的使用:CompletableFuture.runAsync()默认使用ForkJoinPool.commonPool()来执行任务,如果需要更精细地控制线程池的大小或其他属性,可以使用CompletableFuture.supplyAsync()方法并传入自定义的Executor来创建异步任务 。
📝代码示例
package com.fjh.demo.thread;
import com.fjh.demo.dto.scope.ResultView;
import com.fjh.demo.util.DynamicDataUtil;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
/**
 * @ClassName: CompletableFutureDemo
 * @Description: TODO 多线程下异步操作
 * @Author: fengjiahao
 * @Date: 2024/6/15 16:01
 */
public class CompletableFutureDemo {
    public static ResultView resultView;
    public static void main(String[] args)throws Exception {
        CompletableFutureDemo demo = new CompletableFutureDemo();
        //随机生成数据,该工具类可以自己实现ResultView 和DynamicDataUtil都是自己实现
        resultView = DynamicDataUtil.generateRandomObject(ResultView.class);
        //开启两个线程同时处理
       Thread thread1 =  new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"开始处理");
                demo.syncHandle();
            }
        });
        Thread thread2 =  new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"开始处理");
                demo.syncHandle();
            }
        });
       thread1.setName("线程1");
       thread2.setName("线程2");
        thread1.start();
        thread2.start();
    }
    public void syncHandle()  {
        System.out.println(resultView.toString());
        //线程可见性,共享(如果需要线程私有那么就需要使用到ThreadLocal,视场景采用)
        AtomicReference<ResultView> viewAtomic = new AtomicReference<>(resultView);
        CompletableFuture.runAsync(() -> {
            ResultView view= viewAtomic.get();
            view.setName(Thread.currentThread().getName());
            System.out.println("异步修改后:"+view.toString());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println("修改后:"+resultView.toString());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("修改后:"+resultView.toString());
    }
}
-  🪲结果 线程2开始处理 线程1开始处理 ResultView{id=87, name='孙赵', amount=0.7525627958447209} ResultView{id=87, name='孙赵', amount=0.7525627958447209} 修改后:ResultView{id=87, name='孙赵', amount=0.7525627958447209} 修改后:ResultView{id=87, name='孙赵', amount=0.7525627958447209} 异步修改后:ResultView{id=87, name='ForkJoinPool.commonPool-worker-9', amount=0.7525627958447209} 异步修改后:ResultView{id=87, name='ForkJoinPool.commonPool-worker-2', amount=0.7525627958447209} 修改后:ResultView{id=87, name='ForkJoinPool.commonPool-worker-2', amount=0.7525627958447209} 修改后:ResultView{id=87, name='ForkJoinPool.commonPool-worker-2', amount=0.7525627958447209}





![Linux基础命令[29]-chown](https://img-blog.csdnimg.cn/direct/a124b963630c49c5b074e0c9ad831218.png)













