前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >三分钟写一个 Java 多线程

三分钟写一个 Java 多线程

作者头像
FoamValue
修改2020-08-31 17:28:27
4390
修改2020-08-31 17:28:27
举报
文章被收录于专栏:FoamValue

作为一个`老`程序员,我本身是很少会使用多线程去实现业务逻辑的。原因主要有以下两点:

  • 需处理的业务数据体量不大
    • 几百几千的数据量,单线程运行耗时在1s以内。如果使用多线程可以缩短10倍的话,那么也只是从1000ms变成100ms。0.9s的提升是很难于被人感受到的。
  • 对程序员技术要求较高
    • 线程的无限等待、死锁等。
    • 某一线程的失败会涉及复杂的补偿机制。

虽然我很少使用多线程,但是并不是说不去了解她

本文,提供一个简化的案例来展示如何快速使用多线程,即使用线程池。


简单案例

1. 线程池与业务数据准备

代码语言:javascript
复制
public class MultiDemo {

  public void test() {
    // 准备10个线程的线程组
    ExecutorService service = Executors.newFixedThreadPool(10);
    List<Future<Boolean>> rst = new ArrayList<>();
    
    // 业务数据准备,省略。。。
    // 将业务数据分100分,放入线程组中。
    for (int i = 0; i < 100; i++) {
      Future<Boolean> future = service.submit(new CallableDemo(i));
      rst.add(future);
    }
    service.shutdown();
    
    // 线程组处理结果处理
    Boolean flag;
    for (Future<Boolean> future : rst) {
      try {
        flag = future.get();
        if (flag == null || !flag) {
          System.out.println("处理失败 flag: " + flag);
          // 业务数据补偿逻辑
        } else {
          System.out.println("处理成功 flag: " + flag);
        }
      } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
      }
    }

  }
}

2. 业务数据处理逻辑

代码语言:javascript
复制
public class CallableDemo implements Callable<Boolean> {

  private int i;

  public CallableDemo(int i) {
    // 拆分后需要处理的业务数据
    this.i = i;
  }

  @Override
  public Boolean call() throws Exception {
    // 业务数据处理逻辑
    Thread.sleep(100L);
    System.out.println(Thread.currentThread().getName() + " i: " + i);
    return true;
  }
}

3. 运行结果

代码语言:javascript
复制
pool-1-thread-3 i: 90
pool-1-thread-5 i: 96
处理成功 flag: true
处理成功 flag: true
pool-1-thread-7 i: 92
pool-1-thread-9 i: 98
pool-1-thread-6 i: 97
pool-1-thread-2 i: 95
处理成功 flag: true
处理成功 flag: true
处理成功 flag: true
处理成功 flag: true
处理成功 flag: true
处理成功 flag: true
处理成功 flag: true
pool-1-thread-8 i: 99
处理成功 flag: true

注意事项

非常简单的案例,适用于简单的大量数据清理工作。

可能存在的问题:

  • 无限等待
    • future.get(3,TimeUnit.SECONDS);
  • 异常未关闭线程池
    • 将 service.shutdown(); 放入 finally 语句块中
  • 部分线程执行失败
    • 部分失败即全部失败的情况,触发数据库事务回滚。
    • 部分失败不影响其他已经成功的情况,将失败数据放入新的线程池中重试,并设置重试次数。
      • 失败次数超过重试次数后,进行人工干预。
  • 数据表行锁
    • 线程池业务数据拆分要符合数据库表设计
      • 满足主键、唯一约束、分库键等规则进行拆分

小结

时间管理很重要!!!

这个周末,又一次成功“强迫”自己学习。

感谢各位小伙伴的阅读,这里是一个技术人的学习与分享。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FoamValue 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档