Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何检查该池';重用';线_Java_Multithreading_Threadpool - Fatal编程技术网

Java 如何检查该池';重用';线

Java 如何检查该池';重用';线,java,multithreading,threadpool,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");

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

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();
    }
}
公共类线程池测试{
公共静态void main(字符串[]args)引发InterruptedException{
对于(int i=0;i<100;i++){
如果(测试()!=5*100){
抛出新的RuntimeException(“main”);
}
}
test();
}
private static long test()引发InterruptedException{
ExecutorService ExecutorService=Executors.newFixedThreadPool(100);
CountDownLatch CountDownLatch=新的CountDownLatch(100*5);
Set threads=Collections.synchronizedSet(新HashSet());
AtomicLong AtomicLong=新的AtomicLong();
对于(int i=0;i<5*100;i++){
executorService.submit(新的Runnable(){
@凌驾
公开募捐{
试一试{
添加(Thread.currentThread());
atomicLong.incrementAndGet();
countdownlock.countDown();
}捕获(例外e){
系统输出打印ln(e);
}
}
});
}
executorService.shutdown();
倒计时闩锁。等待();
如果(threads.size()!=100){
抛出新的运行时异常(“测试”);
}
返回atomicLong.get();
}
}
如您所见,我使用的是
HashSet

只有当线程不可变时,它的用法才是正确的。至少在测试范围内

据我所知,equals/hashCode不会被重写,因此从对象继承

因此,如果我的测试不正确,请回答错误在哪里。

如果您知道更聪明的方法,请分享。

正如我在评论中提到的,我认为您的代码实际上能够验证
test()
创建100个线程并使用它们执行500个小任务。如果不是这样,您的
RuntimeException
断言肯定会触发

验证这一点的另一种方法是使用计数器来计算实际运行的线程数

我创建了以下单元测试,它使用
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());

}
@测试
public void threadCounter()抛出可丢弃的{
ThreadLocal编号=新的ThreadLocal(){
私有最终AtomicInteger值=新的AtomicInteger();
@凌驾
受保护的整数初始值(){
返回值。getAndIncrement();
}
};
ExecutorService线程池=Executors.newFixedThreadPool(100);
对于(int i=0;i<500;i++){
最终整数计数=i;
threadPool.submit(()->System.out.printf(“%-4s:%-20s-%s\n”,count,Thread.currentThread().getName(),number.get());
}
threadPool.shutdown();
线程池。等待终止(10,时间单位。秒);
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;
}
类ReallySimplePoolWorker{
公共ReallySimplePoolWorker(阻塞队列工作队列){
此->工作队列=工作队列;
}
公开作废运行(){
而(…不关闭…){
Runnable task=workQueue.take();
试一试{
task.run();
}捕获(例外情况除外){
…将异常通知池对象。。。
}
}
}
私有最终阻塞队列工作队列;
}

您能否进一步解释您遇到的问题?您的代码在我的项目中运行良好。@Henrik我不确定我是否理解线程轮询“重用”线程的正确方式我认为您的代码实际上能够验证
test()
创建了100个线程并使用它们执行了500个小任务。如果不是这样的话,
RunTimeException
s将被抛出。“你在寻找更短的方法来证明这一点吗?”亨里克说,尽管那个实验已经进行了很长时间,但我不确定这个输出保证我手头没有junit。通过阅读,我不明白在第一次使用threadLocal之后,您在哪里增加了threadLocal,而且我认为该名称可以重用。如果第一个线程死了,那么第二个线程已经使用了这个名称,那么将代码复制到一个“main”方法以获得相同的效果<每当新线程第一次访问
number
时,就会调用
ThreadLocal
实例的code>initialValue
。这会导致
数字增加。好主意,我问题的第二部分-检查我的代码是否线程安全