2012-03-30 15 views
10

Problema: -Attendere che le discussioni bambino completato: Java Descrizione

Fase 1: Prendere FILE_NAME input da utente a thread principale.

Passaggio 2: Eseguire 10 operazioni su quel file (cioè contare i caratteri, contare le linee ecc.) E tutte queste 10 operazioni devono essere in thread setto. Significa che ci devono essere 10 thread figli.

Passaggio 3: Il thread principale attende fino a quando tutti i thread figli sono stati completati.

Punto 4: Stampa risultato.

Quello che ho fatto: -

ho fatto un codice di esempio con 3 fili. Non voglio il codice operativo del file dalla tua parte.

public class ThreadTest { 
    // This is object to synchronize on. 
    private static final Object waitObject = ThreadTest.class; 
    // Your boolean. 
    private static boolean boolValue = false; 

    public final Result result = new Result(); 

    public static void main(String[] args) { 
     final ThreadTest mytest = new ThreadTest(); 

     System.out.println("main started"); 

     new Thread(new Runnable() { 

      public void run() { 
       System.out.println("Inside thread"); 

       //Int initialiser 
       new Thread(new Runnable() { 

        public void run() { 
         System.out.println("Setting integer value"); 
         mytest.result.setIntValue(346635); 
         System.out.println("Integer value seted"); 
         try { 
          Thread.sleep(1000); 
         } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
        } 
       }).start(); 

       //String initialiser 
       new Thread(new Runnable() { 

        public void run() { 
         System.out.println("Setting string value"); 
         mytest.result.setStringValue("Hello hi"); 
         System.out.println("String value seted"); 
         try { 
          Thread.sleep(1000); 
         } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
        } 
       }).start(); 

       //Boolean initialiser 
       new Thread(new Runnable() { 

        public void run() { 
         System.out.println("Setting boolean value"); 
         mytest.result.setBoolValue(true); 
         System.out.println("Boolean value seted"); 
         try { 
          Thread.sleep(1000); 
         } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
        } 
       }).start(); 

       System.out.println("Thread is finished"); 

       //Notify to main thread 
       synchronized (ThreadTest.waitObject) { 
        ThreadTest.boolValue = true; 
        ThreadTest.waitObject.notifyAll(); 
       }    
      } 
     }).start(); 

     try { 
      synchronized (ThreadTest.waitObject) { 
       while (!ThreadTest.boolValue) { 
        ThreadTest.waitObject.wait(); 
       } 
      } 
     } catch (InterruptedException ie) { 
      ie.printStackTrace(); 
     } 

     System.out.println("main finished"); 
     System.out.println("Result is : " + mytest.result.toString()); 
    } 
} 

Problema: -

Il mio codice di cui sopra non sta dando risposta corretta. Come lo posso fare?

soluzioni alternative:

classe CountDownLatch fa lo stesso. Ma non voglio usare quella classe.

Ho cercato this similar solution e voglio utilizzare solo i metodi di Thread.

+8

letto sul metodo .join() della discussione. – shift66

+0

Se è compito, dovresti buttarlo nel cestino la prossima volta. – Voo

risposta

29

si può fare:

Thread t = new Thread() { 
    public void run() { 
     System.out.println("text"); 
     // other complex code 
    } 
}; 
t.start(); 
t.join(); 

In questo modo si attendere il termine della discussione e solo poi continuare. È possibile join più thread:

for (Thread thread : threads) { 
    thread.join(); 
} 
+0

Join() è solo una soluzione? O modificando del codice nel mio esempio dato posso farlo? – Andy

+0

È la soluzione migliore, più corretta e consigliabile. Probabilmente puoi farlo in altro modo, ma ti avverto che trattare con i thread è noioso e risiedere nelle funzioni della biblioteca il più possibile. –

+1

Ho provato questo, ma un thread attende l'altro thread per iniziare l'esecuzione. Tutti i thread non sono in esecuzione nello stesso tempo. Voglio iniziare tutti i thread e attendere fino a quando tutti sono finiti. –

10

mi sento di raccomandare a guardare il quadro Executors prima, e poi esaminare la CompletionService.

Poi si può scrivere qualcosa del genere:

ExecutorService executor = Executors.newFixedThreadPool(maxThreadsToUse); 
CompletionService completion = new ExecutorCompletionService(executor); 
for (each sub task) { 
    completion.submit(new SomeTaskYouCreate()) 
} 
// wait for all tasks to complete. 
for (int i = 0; i < numberOfSubTasks; ++i) { 
    completion.take(); // will block until the next sub task has completed. 
} 
executor.shutdown(); 
+0

grazie per aver specificato il servizio di completamento .. Lo stavamo cercando da 1 giorno passato :) – xyz

1

Ci sono molti modi per affrontare questo. Considerate CountDownLatch:

import java.util.concurrent.CountDownLatch; 

public class WorkerTest { 
    final int NUM_JOBS = 3; 
    final CountDownLatch countDownLatch = new CountDownLatch(NUM_JOBS); 
    final Object mutex = new Object(); 
    int workData = 0; 

    public static void main(String[] args) throws Exception { 
     WorkerTest workerTest = new WorkerTest(); 
     workerTest.go(); 
     workerTest.awaitAndReportData(); 
    } 

    private void go() { 
     for (int i = 0; i < NUM_JOBS; i++) { 
      final int fI = i; 
      Thread t = new Thread() { 
       public void run() { 
        synchronized(mutex) { 
         workData++; 
        } 
        try { 
         Thread.sleep(fI * 1000); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
        countDownLatch.countDown(); 
       } 
      }; 
      t.start(); 
     } 
    } 

    private void awaitAndReportData() throws InterruptedException { 
     countDownLatch.await(); 
     synchronized(mutex) { 
      System.out.println("All workers done. workData=" + workData); 
     } 
    } 
} 
1

Si consiglia di scegliere CountDownLatch da java.util.concurrent. Da JavaDocs:

Un aiuto sincronizzazione che consente uno o più fili di aspettare che un insieme di operazioni viene eseguito in altri thread completa.

codice di esempio:

import java.util.concurrent.CountDownLatch; 

public class Test { 
    private final ChildThread[] children; 
    private final CountDownLatch latch; 

    public Test() { 
     this.children = new ChildThread[4]; 
     this.latch = new CountDownLatch(children.length); 
     children[0] = new ChildThread(latch, "Task 1"); 
     children[1] = new ChildThread(latch, "Task 2"); 
     children[2] = new ChildThread(latch, "Task 3"); 
     children[3] = new ChildThread(latch, "Task 4"); 
    } 

    public void run() { 
     startChildThreads(); 
     waitForChildThreadsToComplete(); 
    } 

    private void startChildThreads() { 
     Thread[] threads = new Thread[children.length]; 

     for (int i = 0; i < threads.length; i++) { 
      ChildThread child = children[i]; 
      threads[i] = new Thread(child); 
      threads[i].start(); 
     } 
    } 

    private void waitForChildThreadsToComplete() { 
     try { 
      latch.await(); 
      System.out.println("All child threads have completed."); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    private class ChildThread implements Runnable { 
     private final String name; 
     private final CountDownLatch latch; 

     protected ChildThread(CountDownLatch latch, String name) { 
      this.latch = latch; 
      this.name = name; 
     } 

     @Override 
     public void run() { 
      try { 
       // Implementation 
       System.out.println(name + " has completed."); 
      } finally { 
       latch.countDown(); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     Test test = new Test(); 
     test.run(); 
    } 
} 

uscita:

Task 1 è stata completata. L'attività 4 è stata completata. L'attività 3 è stata completata. L'attività 2 è stata completata. Tutti i thread figlio sono stati completati.

2

In Java 8 un approccio di gran lunga migliore è quello di utilizzare parallelStream()

Nota: è molto più facile vedere esattamente ciò che queste operazioni in background stanno facendo.

public static void main(String[] args) { 
    Stream.<Runnable>of(
     () -> mytest.result.setIntValue(346635), 
     () -> mytest.result.setStringValue("Hello hi"), 
     () -> mytest.result.setBoolValue(true)) 
     .parallel() 
     .forEach(Runnable::run); 

    System.out.println("main finished"); 
    System.out.println("Result is : " + mytest.result.toString()); 
} 

ho preso le informazioni di debug e il sonno in quanto questi non alterare l'esito.

Problemi correlati