2013-07-04 7 views
6

Come posso avviare due thread in cui thread1 viene eseguito per primo, thread2 inizia quando thread1 termina mentre il thread del metodo main può continuare il suo lavoro senza il blocco sugli altri due?Esegui due thread che aspettano uno per l'altro mentre il thread principale continua

Ho provato join() tuttavia deve essere chiamato dal thread che deve attendere l'altro, non c'è modo di fare qualcosa come thread2.join (thread1); Se invoco un join all'interno di main(), quindi, in pratica, interrompo l'esecuzione del thread principale e non solo di thread2.

Ho quindi provato con ExecutorService ma ancora lo stesso problema.

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 

public class Test 
{ 
    public static void main(String args[]) throws InterruptedException 
    { 
     System.out.println(Thread.currentThread().getName() + " is Started"); 

     class TestThread extends Thread 
     { 
      String name; 
      public TestThread(String name) 
      { 
       this.name = name; 
      } 

      @Override 
      public void run() 
      { 
       try 
       { 
        System.out.println(this + " is Started"); 
        Thread.sleep(2000); 
        System.out.println(this + " is Completed"); 
       } 
       catch (InterruptedException ex) { ex.printStackTrace(); } 
      } 

      @Override 
      public String toString() { return "Thread " + name; } 
     } 

     ExecutorService executor = Executors.newCachedThreadPool(); 
     executor.execute(new TestThread("1")); 

     boolean finished = executor.awaitTermination(1, TimeUnit.HOURS); 

     if(finished) 
     { 
      //I should execute thread 2 only after thread 1 has finished 
      executor.execute(new TestThread("2")); 
     } 

     //I should arrive here while process 1 and 2 go on with their execution 
     System.out.println("Hello"); 
    } 
} 

#edit: Perché ho bisogno di questo:

ho bisogno di questo perché Thread1 copia gli elementi da una tabella di database in un altro database, Thread2 deve copiare una tabella di collegamento, che fa riferimento alla tabella copiata da Filettatura1 . Di conseguenza thread2 deve iniziare a compilare la sua tabella di collegamento solo quando thread1 ha finito, altrimenti un errore di integrità è dato dal database. Ora immagino di avere diversi thread con priorità diverse a causa di tabelle di collegamento complesse e hai un'idea.

+7

Perché avete bisogno di 2 filetti se obbligatorio eseguire una dopo l'altra? – Tala

+0

Ho aggiunto un "Perché ho bisogno di questo" sopra .. spero sia chiaro – dendini

+0

Non proprio, no. –

risposta

3

il secondo thread può essere personalizzato come questo (prende come argomento il filo precedente):

public static void main(String[] a) { 
    Thread first = new Thread(new Runnable() { 
     @Override 
     public void run() { 

     } 
    }); 

    Thread second = new MyThread(first); 
    first.start(); 
    second.start(); 

    //continue executing 
} 

public static class MyThread extends Thread { 

    private Thread predecessor; 

    public MyThread(Thread predecessor) { 
     this.predecessor = predecessor; 
    } 

    public void run() { 
     if (predecessor != null && predecessor.isAlive()) { 
      try { 
       predecessor.join(); 
      } catch (InterruptedException e) {} 
     } 
     //do your stuff 
    } 
} 
+0

Il codice precedente non funziona, il main continua a funzionare solo dopo che è stato completato. Penso che la seconda blocchi le principali finché il primo non è finito. – dendini

+0

Sicuro! l'ho riparato ora – Tala

3

Sono abbastanza sicuro che hai qualcosa che non va, perché questo deve lavorare e funziona:

new Thread() { 
    @Override 
    public void run() { 
     TestThread t1= new TestThread("1"); 
     TestThread t2= new TestThread("2"); 
     try { 
      t1.start(); 
      t1.join(); 
      t2.start(); 
      t2.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
}.start(); 

L'output è:

main is Started 
Hello 
Thread 1 is Started 
Thread 1 is Completed 
Thread 2 is Started 
Thread 2 is Completed 

Un'altra opzione sarebbe quella di estendere la TestThread per il "Thread 1" per eseguire il lavoro di "Thread 2" dopo che è stato fatto con il proprio lavoro. Qualcosa di simile a questo:

final TestThread t2= new TestThread("2"); 
TestThread t1= new TestThread("1") { 
    @Override 
    public void run() { 
     super.run(); //finish t1 work 
     t2.start(); // start t2 work 
    } 
}; 
t1.start(); 
+0

t1.join(); - il thread principale aspetterà che t1 termini. – Tala

+1

esattamente .. Voglio che il thread principale continui a essere eseguito e non aspettare – dendini

+0

Vedere risposta aggiornata – darijan

2

È possibile utilizzare un CountDownLatch:

creare nel thread principale, passarlo su entrambi i thread e richiamare il conto alla rovescia su di esso nel thread uno quando esce e attendere che venga contato all'inizio del thread 2.

1

Perché non solo avere thread1 essere quello per avviare thread2?

// in main 
new Thread(new Runnable() { 
    @Override public void run() { 
     // do thread1 work 
     new Thread(new Runnable() { 
       @Override public void run() { /* do thread2 work */ } 
     }).start(); 
    } 
}).start(); 

Tuttavia, non è affatto chiaro perché si vuole fare questo invece di avere solo Thread1 fare il 100% del lavoro di fondo.

+0

Forse questa ovvia soluzione è troppo ovvia - un altro poster l'ha suggerito e ha avuto downvoted per qualche motivo. È sicuramente il modo più semplice, molto più semplice dei suggerimenti di segnalazione espliciti. –

0

Domanda sciocca, ma se si suppone che il thread 2 venga eseguito al termine del thread 1 ... perché non avviarlo dal thread 1?

O forse solo il thread 1 attiva un evento e il thread principale può lanciare il nuovo in risposta a quello.

Ho trovato l'esempio this, dovrebbe funzionare per voi.

+0

Questo dovrebbe essere un commento, non una risposta. –

+0

Cosa? È un modo perfettamente ragionevole per ottenere ciò che l'OP sembra volere. –

+0

... anche se è un requisito stupido. –

1

È possibile utilizzare SingleThreadExecutor per eseguire un compito dopo l'altro Java doc

Così sarà mettere il vostro compito uno dopo l'altro e che verrà eseguito in sequenza senza bloccare thread principale

0

È possibile eseguire due fili, uno dopo altro utilizzando diversi modi:

  1. utilizzando il metodo join(). es:

    Thread t1=new Thread(new Runnable() { 
        @Override 
        public void run() { 
         for (int i = 0; i < 4; i++) { 
          System.out.println("A " + i); 
         } 
        } 
    }); 
    Thread t2=new Thread(new Runnable() { 
        @Override 
        public void run() { 
         for (int i = 0; i < 4; i++) { 
          System.out.println("B " + i); 
         } 
        } 
    }); 
    
    1. utilizzando wait() e notify() metodi: ex.

`

{ 
public class NotiffyAllExample { 

    int flag = 1; 

    public static void main(String[] args) { 

     NotiffyAllExample notiffyAllExample = new NotiffyAllExample(); 

     A1 a = new A1(notiffyAllExample); 
     B1 b = new B1(notiffyAllExample); 
     C1 c = new C1(notiffyAllExample); 
     a.start(); 
     b.start(); 
    } 
} 

class A1 extends Thread { 

    NotiffyAllExample notiffyAllExample; 

    public A1(net.citigroup.mexico.pg.test.test.NotiffyAllExample notiffyAllExample) { 
     this.notiffyAllExample = notiffyAllExample; 
    } 

    @Override 
    public void run() { 

     try { 
      synchronized (notiffyAllExample) { 

       for (int i = 0; i < 4; i++) { 

        while (notiffyAllExample.flag != 1) { 
         notiffyAllExample.wait(); 
        } 
        System.out.print("A "); 
       } 
       notiffyAllExample.flag = 2; 
       notiffyAllExample.notifyAll(); 
      } 
     } catch (Exception e) { 
      System.out.println("Exception 1 :" + e.getMessage()); 
     } 

    } 
} 

class B1 extends Thread { 

    NotiffyAllExample notiffyAllExample; 

    public B1(NotiffyAllExample notiffyAllExample) { 
     this.notiffyAllExample = notiffyAllExample; 
    } 

    @Override 
    public void run() { 
     try { 
      synchronized (notiffyAllExample) { 

       for (int i = 0; i < 4; i++) { 

        while (notiffyAllExample.flag != 2) { 
         notiffyAllExample.wait(); 
        } 
        System.out.print("B "); 
       } 
       notiffyAllExample.flag = 1; 
       notiffyAllExample.notifyAll(); 

      } 
     } catch (Exception e) { 
      System.out.println("Exception 2 :" + e.getMessage()); 
     } 

    } 
} 
} 

`