Reputation: 37116
To check the subject I have wrote the code:
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();
}
}
As you can see I use HashSet<Thread>
Its usage will be correct only if Thread immutable. at least within test.
As I understand equals/hashCode is not overriden and thus inherit from Object.
Thus, please answer if my test incorrect and where is mistake.
If you know more clever way, please share this.
Upvotes: 3
Views: 63
Reputation: 27190
I am not sure that I undestand correct how thread [pool] 'reuses' threads.
A pool thread (a.k.a., worker thread) has a run()
method, just like any other thread, and that's where the "re-use" happens. Basically, the worker thread's run()
method picks tasks (i.e., the client-supplied Runnable
objects) from a queue, and it runs them:
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;
}
Upvotes: 1
Reputation: 7157
As mentioned in my comment, I would argue that your code actually manages to verify that test()
creates 100 threads and executes 500 small tasks using them. Your RuntimeException
assertions would definitely fire if that was not the case.
Another approach to verifying this is to use a ThreadLocal
to count the actual number of threads running.
I've created the following unit test which uses a ThreadLocal
to count the number of threads created by the Executor
. Try studying its output to be convinced of the number of threads created.
@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());
}
Upvotes: 2