为了检查主题,我编写了代码:
public class ThreadPoolTest {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
if (test() != 5 * 100) {
throw new RuntimeException("main");
}
}
test();
}
private static long test() throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(100);
CountDownLatch countDownLatch = new CountDownLatch(100 * 5);
Set<Thread> threads = Collections.synchronizedSet(new HashSet<>());
AtomicLong atomicLong = new AtomicLong();
for (int i = 0; i < 5 * 100; i++) {
executorService.submit(new Runnable() {
@Override
public void run() {
try {
threads.add(Thread.currentThread());
atomicLong.incrementAndGet();
countDownLatch.countDown();
} catch (Exception e) {
System.out.println(e);
}
}
});
}
executorService.shutdown();
countDownLatch.await();
if (threads.size() != 100) {
throw new RuntimeException("test");
}
return atomicLong.get();
}
}
如您所见,我使用HashSet< Thread>
仅当Thread不可变时,它的用法才是正确的.至少在测试范围内.
据我了解,equals / hashCode没有被覆盖,因此从Object继承.
因此,如果我的测试不正确以及错误在哪里,请回答.
如果您知道更聪明的方法,请分享.
解决方法:
如我的评论中所述,我认为您的代码实际上可以验证test()创建了100个线程并使用它们执行了500个小任务.如果不是这种情况,肯定会触发您的RuntimeException断言.
验证此问题的另一种方法是使用ThreadLocal
来计数正在运行的实际线程数.
我创建了以下单元测试,该单元测试使用ThreadLocal来计数执行器创建的线程数.尝试研究其输出,以确信所创建的线程数.
@Test
public void threadCounter() throws Throwable {
ThreadLocal<Integer> number = new ThreadLocal<Integer>() {
private final AtomicInteger values = new AtomicInteger();
@Override
protected Integer initialValue() {
return values.getAndIncrement();
}
};
ExecutorService threadPool = Executors.newFixedThreadPool(100);
for (int i = 0 ; i < 500 ; i++) {
final int count = i;
threadPool.submit(() -> System.out.printf("%-4s : %-20s - %s\n", count, Thread.currentThread().getName(), number.get()));
}
threadPool.shutdown();
threadPool.awaitTermination(10, TimeUnit.SECONDS);
Assert.assertEquals(100, number.get().intValue());
}