多线程应用:子线程任务影响主线程

业务场景

保存/复制某棵树,还需要保存树的分支节点以及分支上的叶子特征

业务分析

保存树节点到A表,遍历得到树分支节点,查询对应叶子信息,批量保存到B表。如果查询某个叶子节点失败则提示保存树失败。因为保存的树就不是之前树的结构和样子了(业务需要保存一模一样整棵树)。

业务探讨
如果串行执行,那就是每个节点查询以及保存的时间总和。于是引入多线程,但异步执行不获取返回值的话,时间是主线程的时间,但也得不到子线程的状态,捕获不到子线程的异常在主线程处理。所以引入Callable,带返回值的线程,返回值有两种Future和FutureTask,使用泛型能很好的兼容业务,根据不同场景定义不同返回值。

更重要的是,在子线程业务处理时,如果出现异常返回null或者false了,可以根据泛型定义不同类型,在最后循环处理线程执行结果。达到主线程子线程的一致性。

private final static ExecutorService THREAD_EXECUTOR = Executors.newFixedThreadPool(16);

public int getSum(int n) throws ExecutionException, InterruptedException {
   int sum = 0;
   List<Future<Integer>> list = new ArrayList<Future<Integer>>();
   for (int i = 0; i < n; i++) {
       Future<Integer> future = executeThread(i);
       sum += future.get();
   }
   return sum;
}

private Future<Integer> executeThread(final int i) {
   Future<Integer> future = THREAD_EXECUTOR.submit(new Callable<Integer>() {
       public Integer call() throws Exception {
           Thread.sleep(5000);
           return i;
       }
   });
   return future;
}

优化前执行结果
虽然写了多线程,但边执行边get返回值,实际相当于程序是同步执行,并没有达到异步线程的目的,所以改造后代码,只有改造线程调用的方法,如下:

public int getSum(int n) throws ExecutionException, InterruptedException {
    int sum = 0;
    List<Future<Integer>> list = new ArrayList<Future<Integer>>();
    for (int i = 0; i < n; i++) {
        Future<Integer> future = executeThread(i);
        list.add(future);
    }
    for (Future<Integer> future : list) {
        if (null != future.get()) {
            sum += future.get();
        }
    }
    return sum;
}

异步监听线程执行结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值