2017-02-16 3 views
3

das Thema, das ich den Code geschrieben haben, zu prüfen:, wie das Pool überprüfen ‚wieder verwendet‘ Thema

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

Wie Sie ich HashSet<Thread>

Seine Verwendung nur richtig sein, wenn Faden unveränderlich verwenden sehen können. zumindest innerhalb des Tests.

Wie ich verstehe, ist equals/hashCode nicht überschrieben und somit von Object erben.

So, bitte antworte, wenn mein Test falsch ist und wo Fehler ist.
Wenn Sie kluger Weg wissen, bitte teilen Sie dies.

+0

Können Sie weiter zu erklären, welches Problem Sie begegnen? Ihr Code läuft in meinem Projekt einwandfrei. – Henrik

+0

@Henrik Ich bin mir nicht sicher, ob ich richtig erklaere, wie thread poll 'Threads wiederverwendet' – gstackoverflow

+0

Ich würde behaupten, dass Ihr Code es tatsächlich schafft, zu verifizieren, dass 'test()' 100 Threads erstellt und 500 kleine Tasks ausführt. Ihre 'RunTimeException's würden geworfen, wenn das nicht der Fall war. Suchen Sie nach kürzeren Wegen, dies zu beweisen? – Henrik

Antwort

2

Wie in meinem Kommentar erwähnt, würde ich behaupten, dass Ihr Code tatsächlich zu überprüfen, dass test() 100 Threads erstellt und führt 500 kleine Aufgaben mit ihnen. Ihre RuntimeException Behauptungen würden definitiv feuern, wenn das nicht der Fall war.

Eine andere Methode, dies zu überprüfen, ist die Verwendung einer ThreadLocal, um die tatsächliche Anzahl der laufenden Threads zu zählen.

Ich habe den folgenden Komponententest erstellt, der ThreadLocal verwendet, um die Anzahl der Threads zu zählen, die von Executor erstellt werden. Versuchen Sie, die Ausgabe zu studieren, um von der Anzahl der erstellten Threads überzeugt zu sein.

@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

Ich habe keine Junit zur Hand. Durch das Lesen verstehe ich nicht, wo du threadLocal nach dem ersten Mal incrent – gstackoverflow

+0

Auch ich denke, Name kann wiederverwendet werden. Wenn der erste Thread gestorben ist - Sekunde hat diesen Namen verwendet – gstackoverflow

+0

Kopieren Sie den Code in eine'ain'-Methode für den gleichen Effekt. 'initialValue' der' ThreadLocal'-Instanz wird immer dann aufgerufen, wenn ein neuer Thread zum ersten Mal auf 'number' zugreift. Dies bewirkt, dass "Nummer" inkrementiert wird. – Henrik

1

Ich bin nicht sicher, dass ich richtig undestand wie Thread [Pool] 'Umnutzungen' Threads.

Ein Pool Gewinde (a.k.a., Arbeiter-Thread) ein run() Verfahren, wie jedes anderes Gewinde, und das ist, wo die "Wiederverwendung" geschieht. Grundsätzlich ist der Worker-Thread run() Methode nimmt Aufgaben (das heißt die vom Client bereitgestellte Runnable Objekte) aus einer Warteschlange, und es läuft ihnen:

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; 
} 
Verwandte Themen