如何检查该池'重复使用'线

时间:2017-02-16 13:36:39

标签: java multithreading threadpool

为了检查主题我写了代码:

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。

因此,如果我的测试不正确以及错误在哪里,请回答 如果你知道更聪明的方式,请分享一下。

2 个答案:

答案 0 :(得分:2)

正如我的评论中所提到的,我认为你的代码实际上设法验证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());

}

答案 1 :(得分:1)

  

我不确定我是否正确解决了线程[池]'重用'线程的问题。

池线程(a.k.a。,工作线程)具有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;
}
相关问题