Java 并发编程基础实例:Runnable 与固定大小线程池

背景

之前虽然在书里学过 Java 并发编程的基础,但一直没有在实践中用到过。直到上周,终于在项目看到了一个活生生的例子。

这个例子也非常基础,需求大概是这样的:

  • 我们基于 Lucene 做站内搜索引擎,每天都需要重新构建一次索引,因为每天都会产生新内容(之所以彻底重新构建一遍,是因为内容量也没有那么大,与其在原有索引后面追加新索引,不如重新构建,因为这样查询起来更快);
  • 在构建索引时,需要请求 CMS 数据库,拿到全部内容的相关数据,例如标题、关键字等等,基于这些字段构建索引;
  • 由于请求 CMS 数据库涉及网络 I/O,所以程序大量时间都在等待网络请求结果。这种情况下,如果能利用多个线程并发操作(线程数 > CPU 核数),就应该能获得较大的性能提升;

实现起来是这样:

  • 使用固定的线程数 20(我也不知道是怎么得到这个数字的,有空可以研究下);
  • 把需要索引的内容均分成 20 份,每个线程负责为自己的那一份内容写入索引;

具体到 Java 层面:

  • 使用 Executors.newFixedThreadPool(20) 创建一个线程数为 20 的固定大小线程池;
  • 声明一个 worker class 来 implement Runnable,在其 run() 方法下写每个线程要执行的逻辑;
  • 创建 20 个 worker 实例,都使用 executor.execute() 来执行;

下面简单来看一看。

Runnable

首先来看一看 Runnable 这个东西。这大概是 Java 里使用线程最基础、最直白的方式了吧!

在我们这个例子里,每个线程之间是相互独立的,而且执行的操作逻辑是一样的,只不过参数不同(每个线程都是请求内容、写入索引,只不过每个线程所负责的内容不同,比如线程 1 负责 0-99 号内容,线程 2 负责 100-199 号,等等)。在这种情况下,使用 Runnable 就可以轻松达到目的:

@AllArgsConstructor
class MyWorker implements Runnable {

    private int someParam;

	private int someOtherParam;
	
	// ...其他参数

    @Override
    public void run() {
    	// 这里可以基于 someParam 和 someOtherParam 等参数,写每个线程执行的逻辑
    }

Executors.newFixedThreadPool

那么该如何执行这些线程呢?

这个例子中的需求也比较简单,只需要固定的线程数:

// 创建一个大小固定为 20 的线程池
ExecutorService executor = Executors.newFixedThreadPool(20);

// 依次启动 20 个线程
for (int i = 0; i < 20; i++) {
	try{
		// 创建 worker,这里可以加很多参数,作为示例只写了两个
	    Runnable worker = new MyWorker(i, someOtherParam);
	    // 启动!
	    executor.execute(worker);
	} catch (Exception e) {
	    log.error("worker failed", e);
	}
}

// 关闭 executor,不再接受新任务(不过上面 20 个任务此时一定还在执行)
executor.shutdown();

其实平时用到 Executors.newFixedThreadPool() 的概率应该不大,因为它有个缺陷:如果线程池没有空闲线程,而新任务又源源不断被创建,那么这些任务会被放在一个等待队列中,但这个等待队列没有数量上限,可能会越来越大,直到内存不够用。所以正常来说是应该设定等待队列上限的。

不过这里就没有这个问题,因为任务并不是动态创建的,而是固定只有 20 个。在这种情况下使用 Executors.newFixedThreadPool() 就非常合理了!

小结

这次遇到的是一个非常简单的 Java 并发编程例子,作为入门很合适。之后有机会再学习更高级的技巧吧!

参考链接

“implements Runnable” vs “extends Thread” in Java
Reason for calling shutdown() on ExecutorService
Executor Thread Pool - limit queue size and dequeue oldest

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值