2017-02-16 3 views
3

Чтобы проверить эту тему я написал код:Как проверить, что бассейн «повторно» тему

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.

Таким образом, ответьте, если мой тест неверен и где ошибка.
Если вы знаете более умный способ, поделитесь этим.

+0

Можете ли вы объяснить, кроме того, что проблема Вы сталкиваетесь? Ваш код отлично работает в моем проекте. – Henrik

+0

@Henrik Я не уверен, что я правильно понял, как потоковый опрос «повторяет» потоки – gstackoverflow

+0

Я бы сказал, что ваш код действительно проверяет, что 'test()' создает 100 потоков и выполняет 500 небольших задач, используя их. Ваше 'RunTimeException' будет выброшено, если это не так. Вы ищете более короткие способы доказать это? – Henrik

ответ

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()); 

} 
+0

У меня нет junit под рукой. Читая, я не понимаю, где вы начинаете threadLocal после первого раза – gstackoverflow

+0

Также я думаю, что имя можно использовать повторно. Если первая нить умерла - вторая использует это имя – gstackoverflow

+0

Скопируйте код в метод aain' для того же эффекта. 'initialValue' экземпляра' ThreadLocal' вызывается каждый раз, когда новый поток обращается к 'number' в первый раз. Это приводит к увеличению числа. – Henrik

1

Я не уверен, что я правильно undestand хау нить [пул] нитей 'повторно.

пул потоков (а.к.а., рабочий поток) имеет метод 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; 
} 
Смежные вопросы