多线程 | FutureTask实践

FutureTask是多线程编程中经常用到的一个类,在线程池中,它常常以 executor.submit() 方法调用,它返回了一个Future对象,从而实现了多线程编程中获取异步结果的一种途径。

FutureTask是一个封装了任务的类,可以理解成是Runnable/Callable的包装类。原生的Runnable/Callable都是同步执行,FutureTask像是一个单独的容器,通过持有任务的成员变量,并获取执行该任务的线程,让任务在这FutureTask中运行,然后将运行结果存放在容器中。调用者可以在不同的阶段获取这个结果。

1、线程池创建


public class ThreadPoolUtils  {
    //可用处理器的Java虚拟机的数量
    private static int CORE_SIZE  =  Runtime.getRuntime().availableProcessors();
    private static int CORE_MAX_SIZE =  Runtime.getRuntime().availableProcessors()*2;
    // volatile 保证线程的存可见性
    private static volatile ExecutorService executorService ;
    private static ExecutorService getInstance(){
        synchronized (ThreadPoolUtils.class){
            if(executorService == null){
                synchronized (ThreadPoolUtils.class){
                    return executorService = new ThreadPoolExecutor(CORE_SIZE, CORE_MAX_SIZE , 10, TimeUnit.SECONDS,
                            new LinkedBlockingQueue<>(), Executors.defaultThreadFactory(),
                            new ThreadPoolExecutor.AbortPolicy());
                }
            }
            return executorService;
        }
    }

    public static void submit(Runnable runnable) {
        getInstance().submit(runnable);
    }

    public static <T> Future<T> submitCall(Callable<T> callable) {
        return getInstance().submit(callable);
    }

    public static void synCall(Runnable... runnableSet) {
        for (Runnable runnable : runnableSet) {
            getInstance().submit(runnable);
        }
    }

2、查询测试



@RestController
@RequestMapping("/future")
@RequiredArgsConstructor
@Api(value = "FutureTask测试",tags = "FutureTask测试")
@Log4j2
public class ThreadPoolController {

    private final ThreadPoolService threadPoolService;
    @GetMapping("/search")
    @ApiOperation(value = "正常依次查询")
    public Result<List<String>> search() throws InterruptedException {
        return threadPoolService.searchOrdinary();
    }

    @GetMapping("/searchConcurrency")
    @ApiOperation(value = "FutureTask并发查询")
    public Result<List<String>> searchConcurrency() throws InterruptedException, ExecutionException {
        return threadPoolService.searchConcurrency();
    }
}
public interface ThreadPoolService {

    Result<List<String>> searchOrdinary() throws InterruptedException;

    Result<List<String>> searchConcurrency() throws InterruptedException, ExecutionException;
}


@Service
@Log4j2
public class ThreadPoolServiceImpl implements ThreadPoolService {

    public String select1(String str) throws InterruptedException {
        Thread.sleep(1000);
        return str;
    }
    /**正常的依次查询*/
    @Override
    public Result<List<String>> searchOrdinary() throws InterruptedException {
        long l = System.currentTimeMillis();
        List<String> list = Lists.newArrayList();
        list.add(select1("查询一次"));
        list.add(select1("查询二次"));
        list.add(select1("查询三次"));
        list.add(select1("查询四次"));
        log.info("查询耗时:{}",System.currentTimeMillis()-l);
        return Result.success(list);
    }
     /**使用FutureTask并发查询查询*/
    @Override
    public Result<List<String>> searchConcurrency() throws ExecutionException, InterruptedException {
        long l = System.currentTimeMillis();
        Future<String> search1 = ThreadPoolUtils.submitCall(() -> select1("查询一次"));
        Future<String> search2 = ThreadPoolUtils.submitCall(() -> select1("查询二次"));
        Future<String> search3 = ThreadPoolUtils.submitCall(() -> select1("查询三次"));
        Future<String> search4 = ThreadPoolUtils.submitCall(() -> select1("查询四次"));
        List<String> list = Lists.newArrayList();
        list.add(search1.get());
        list.add(search2.get());
        list.add(search3.get());
        list.add(search4.get());
        log.info("查询耗时:{}",System.currentTimeMillis()-l);
        return Result.success(list);
    }
//get 时集中放在后面,以免线程阻塞。

正常依次查询:耗时4049

FutureTask并发查询:耗时 1008

FutureTask 并发执行查询可以在复杂查询时提高效率。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值