Java 1.6中如何用固定线程数实现多线程For循环?
Java 1.6 实现固定线程数的多线程For循环
老哥,我太懂你这种被Java版本卡脖子的痛苦了——Java 8的Stream多线程确实香,但1.6只能老老实实用ExecutorService,其实你之前的思路完全没问题,大概率是细节没处理到位导致跑不起来。我把正确的实现方式和踩过的坑给你理得明明白白:
核心实现思路
我们用Executors.newFixedThreadPool(10)创建固定大小的线程池,把循环里的每个任务包装成Runnable或Callable提交到线程池,然后等待所有任务执行完毕,最后必须正确关闭线程池(这步90%的人第一次用都会忘!)
方式一:用invokeAll批量提交任务(推荐,代码更简洁)
invokeAll会自动阻塞直到所有提交的任务都完成,非常适合这种批量循环的场景:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; // 你的业务类上下文 public class YourBusinessService { public void processExampleData(List<ExampleType> exampleData) { // 创建10个线程的固定线程池 ExecutorService executor = Executors.newFixedThreadPool(10); try { // 把每个循环任务包装成Callable(支持抛出检查异常) List<Callable<Void>> tasks = new ArrayList<Callable<Void>>(); for (final ExampleType ex : exampleData) { // Java 1.6匿名内部类必须访问final变量! tasks.add(new Callable<Void>() { @Override public Void call() throws Exception { // 执行你的业务方法 exampleFunction(ex.getSomeData()); return null; // Callable必须返回值,void场景返回null即可 } }); } // 等待所有任务执行完成 executor.invokeAll(tasks); } catch (InterruptedException e) { // 处理中断:恢复线程中断状态,避免后续逻辑异常 Thread.currentThread().interrupt(); e.printStackTrace(); } finally { // 正确关闭线程池:先停止接受新任务,再等待现有任务完成 executor.shutdown(); try { // 等待60秒让线程池完全关闭,超时则强制终止剩余线程 if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); Thread.currentThread().interrupt(); } } } // 你的业务方法示例 private void exampleFunction(Object someData) { // 这里写你的实际业务逻辑 System.out.println("处理数据:" + someData + ",线程:" + Thread.currentThread().getName()); } } // 你的示例数据类 class ExampleType { private Object someData; public Object getSomeData() { return someData; } // 构造器等其他方法 }
方式二:用CountDownLatch精细控制任务完成时机
如果需要更灵活的等待逻辑(比如中途可以取消任务),可以用CountDownLatch:
import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class YourBusinessService { public void processExampleData(List<ExampleType> exampleData) { int taskCount = exampleData.size(); CountDownLatch latch = new CountDownLatch(taskCount); ExecutorService executor = Executors.newFixedThreadPool(10); try { for (final ExampleType ex : exampleData) { executor.execute(new Runnable() { @Override public void run() { try { exampleFunction(ex.getSomeData()); } finally { // 不管任务成功失败,都要减计数,避免死等 latch.countDown(); } } }); } // 等待所有任务完成 latch.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } finally { // 同样要正确关闭线程池 executor.shutdown(); try { if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); Thread.currentThread().interrupt(); } } } private void exampleFunction(Object someData) { // 业务逻辑 System.out.println("处理数据:" + someData + ",线程:" + Thread.currentThread().getName()); } }
你之前可能踩的坑
- 没加
final修饰循环变量:Java 1.6中匿名内部类只能访问final的外部变量,没加的话直接编译失败 - 没等待任务完成就结束程序:线程池的线程是非守护线程,如果不等待就退出,任务可能还没执行完就被终止
- 没关闭线程池:线程池会一直持有线程资源,导致程序无法正常退出
- 没处理中断异常:中断异常会打断等待逻辑,必须恢复线程的中断状态,避免后续逻辑出错
内容的提问来源于stack exchange,提问作者David Davaatulga
相关产品推荐
相关产品推荐

