如何检查池“重用”主题
问题描述:
要检查我已经写的代码主题:如何检查池“重用”主题
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>
它的用法是正确的只有螺纹不变。至少在测试中。
据我所知equals/hashCode没有被覆盖,因此从Object继承。
因此,请回答如果我的测试不正确,哪里出错。
如果你知道更聪明的方式,请分享一下。
答
正如我在评论中提到的,我会争辩说,你的代码实际上设法验证test()
创建100个线程并使用它们执行500个小任务。如果不是这样,你的断言肯定会触发。
验证此问题的另一种方法是使用ThreadLocal
来计算实际运行的线程数。
我创建了以下单元测试,它使用ThreadLocal
来计算由Executor
创建的线程数。尝试研究其输出以确信所创建线程的数量。
@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());
}
答
我不知道,我已了解如何正确线程[池]“重复使用”线程。
池线程(也叫做工作线程)具有run()
方法,就像任何其他的线程,而这也正是“再利用”发生。基本上,工作线程的run()
方法挑选从队列任务(即客户端提供Runnable
对象),并运行它们:
class ReallySimplePoolWorker {
public ReallySimplePoolWorker(BlockingQueue<Runnable> workQueue) {
this->workQueue = workQueue;
}
public void Run() {
while (...not shutting down...) {
Runnable task = workQueue.take();
try {
task.run();
} catch (Exception ex) {
...notify the pool object of the exception...
}
}
}
private final BlockingQueue<Runnable> workQueue;
}
你能解释进一步你遇到什么问题?你的代码在我的项目中运行良好。 – Henrik
@Henrik我不确定我是否正确地调整了线程轮询“重用”线程的方式 – g*
我会争辩说,您的代码实际上设法验证test()是使用它们创建100个线程并执行500个小任务。如果情况不是这样,你的'RunTimeException'将被抛出。你正在寻找更短的方式来证明这一点? – Henrik