2012-03-30 9 views
10

Problema: -Esperar hasta que las roscas niño completado: Java Descripción

Paso 1: Tome FILE_NAME de entrada de usuario en hilo principal.

Paso 2: Realice 10 operaciones en ese archivo (es decir, cueres de recuento, recuentos, etc.), y todas esas 10 operaciones deben estar en hilos septados. Significa que debe haber 10 hilos secundarios.

Paso 3: El hilo principal espera hasta que se completen todos los subprocesos secundarios.

Paso 4: Resultado de la impresión.

Lo que hice: -

Hice un código de ejemplo con 3 hilos. No deseo el código de operación de archivos de su lado.

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: -

Mi código anterior no está dando respuesta correcta. ¿Cómo puedo hacer eso?

soluciones alternativas:

clase CountDownLatch hace lo mismo. Pero no quiero usar esa clase.

Miré this similar solution y quiero usar métodos de subproceso solamente.

+8

lea sobre .join() método de Thread. – shift66

+0

Si es tarea debe tirarla como basura la próxima vez. – Voo

Respuesta

29

que puede hacer:

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

De esta manera se va a esperar hasta que termine el hilo y justo entonces continuar. Puede join varios subprocesos:

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

Is join() es solo una solución? O modificando algún código en mi ejemplo dado, ¿puedo hacer eso? – Andy

+0

Es la mejor solución, la más correcta y recomendable. Probablemente puedas hacerlo de otra manera, pero te lo advierto: manejar los hilos es tedioso y resguardar las funciones de la biblioteca tanto como puedas. –

+1

Intenté esto pero un hilo espera el otro hilo para comenzar a ejecutar. Todos los hilos no se están ejecutando al mismo tiempo. Quiero iniciar todos los hilos y esperar hasta que todos hayan terminado. –

10

recomendaría mirar el marco Executors primero, y luego buscar en el CompletionService.

Entonces se puede escribir algo como esto:

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

gracias por especificar el servicio de compleción ... Lo estaba buscando desde el pasado 1 día :) – xyz

1

Hay muchas maneras de abordar esto. Considere 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

es posible que desee elegir CountDownLatch de java.util.concurrent. De JavaDocs:

Una ayuda de sincronización que permite a uno o más hilos que esperar hasta que un conjunto de operaciones se realiza en otros hilos completa.

Código de ejemplo:

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

Salida:

Tarea 1 ha completado. Tarea 4 ha completado. Tarea 3 ha completado. La Tarea 2 se ha completado. Todos los hilos secundarios se han completado.

2

En Java 8 un enfoque mucho mejor es utilizar parallelStream()

Nota: es mucho más fácil ver exactamente lo que estas tareas en segundo plano están haciendo.

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

Saqué la información de depuración y la suspensión, ya que estos no alteran el resultado.

Cuestiones relacionadas