如何检查池“重用”主题

如何检查池“重用”主题

问题描述:

要检查我已经写的代码主题:如何检查池“重用”主题

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继承。

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

+0

你能解释进一步你遇到什么问题?你的代码在我的项目中运行良好。 – Henrik

+0

@Henrik我不确定我是否正确地调整了线程轮询“重用”线程的方式 – g*

+0

我会争辩说,您的代码实际上设法验证test()是使用它们创建100个线程并执行500个小任务。如果情况不是这样,你的'RunTimeException'将被抛出。你正在寻找更短的方式来证明这一点? – Henrik

正如我在评论中提到的,我会争辩说,你的代码实际上设法验证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()); 

} 
+0

我没有junit在手边。通过阅读我不明白你在哪里incrent threadLocal第一次之后 – g*

+0

另外我觉得名字可以重用。如果第一个线程死了 - 第二个线程已经使用了这个名字 – g*

+0

将代码复制到“main”方法以获得相同效果。每当新线程第一次访问'number'时,就会调用'ThreadLocal'实例的'initialValue'。这会导致'号码'增加。 – Henrik

我不知道,我已了解如何正确线程[池]“重复使用”线程。

池线程(也叫做工作线程)具有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; 
}