如何检查那个池 'reuses' 线程
How to check that pool 'reuses' Thread
为了检查主题我写了代码:
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 个小任务。如果不是这种情况,您的 RuntimeException
断言肯定会触发。
验证这一点的另一种方法是使用 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());
}
I am not sure that I undestand correct how thread [pool] 'reuses' threads.
池线程(a.k.a., 工作线程)有一个run()
方法,就像任何其他线程一样,这就是"re-use" 发生。基本上,工作线程的 run()
方法从队列中选择 tasks(即 client-supplied 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;
}
为了检查主题我写了代码:
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 个小任务。如果不是这种情况,您的 RuntimeException
断言肯定会触发。
验证这一点的另一种方法是使用 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());
}
I am not sure that I undestand correct how thread [pool] 'reuses' threads.
池线程(a.k.a., 工作线程)有一个run()
方法,就像任何其他线程一样,这就是"re-use" 发生。基本上,工作线程的 run()
方法从队列中选择 tasks(即 client-supplied 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;
}