2011-01-13 10 views
5

Ho una classe Note e una classe Meeting. C'è un ArrayList denominato noteList nella classe Note. Quando viene creato un oggetto di Meeting, esso viene quindi registrato nel numero noteList.come avviare due thread contemporaneamente (o all'ora di chiusura)

Voglio solo dimostrare nella classe principale che due oggetti di Meeting possono essere creati allo stesso tempo (o al momento della chiusura). Il mio programma è:

public class Note{ 
    //some field and method hier 
    public void add(Meeting m){ 
     notes.add(m); 
    } 
    private static final List<Entry> notes = 
     Collections.synchronizedList(new ArrayList<Entry>()); 
} 

public class Meeting implements Runnable{ 
    public Meeting(Note note_1,Note note_2,Calendar calendar){ 
     note_1.add(this); 
     note_2.add(this);} 
     //some method 
    } 

    public class Test implements Runnable{ 
     public static void main(String[] args) { 
      Note note_1 = new Note();     
      Note note_2 = new Note(); 
      Meeting m_1 = new Meeting(note_1,note_2); 
      Meeting m_2 = new Meeting(note_2,note_1) 
      Thread t1 = new Thread(m_1); 
      Thread t2 = new Thread(m_2) 
      t1.start(); 
      t2.start(); 
     } 
     //t1,t2 are two thread and they start one to one(not at the same time). 

Ho letto da nessuna parte che wait(), notify() o notifyAll() possono essere utilizzati, ma devono essere utilizzati in un metodo sincronizzato. Non ho metodi sincronizzati nel mio programma.

+0

Nel codice come scritto, 'm_1' viene sempre creata (istanziato) prima di' m_2' se saranno entrambi presenti contemporaneamente in memoria fino a quando il GC decide di pulirli. Intendi qualcos'altro? In ogni caso, se si cerca perché il blocco a doppio controllo per singleton non funziona, si otterrà un'ottima panoramica dei problemi di sincronizzazione in Java. – CurtainDog

+0

Penso che manchi.Voglio dire come si possono creare m_1 e m_2 (istanziati) allo stesso tempo (o al momento della chiusura) – echo

+0

Si stanno utilizzando metodi sincronizzati perché synchronizedList() restituisce una lista che ha sincronizzato tutto il suo metodo. –

risposta

15

Questo è il più vicino possibile per avviare i due thread.

Che cosa si potrebbe fare per sincronizzare i metodi di esecuzione ancora più è di farli aspettare su una CountDownLatch sulla parte superiore dei loro metodi di esecuzione.

Ciò che fa è eliminare il sovraccarico di creare e avviare i thread (la parte che si verifica prima dell'esecuzione del metodo di esecuzione) e forse anche alcune stranezze di programmazione anomala. Tuttavia non si ha alcuna garanzia sul modo in cui il codice dopo il latch sarà simultaneo.

CountDownLatch latch = new CountDownLatch(2); 

Runnable r1 = new Meeting(latch); 
Runnable r2 = new Meeting(latch); 


// in Meeting 

private final CountDownLatch latch; 

public void run(){ 

    latch.countDown(); 
    latch.await(); 

    // other code 
} 
+1

+1 Vedi anche, http://stackoverflow.com/questions/1909622 – trashgod

+0

Puoi solo garantire che un thread non passi attendere fino a quando il secondo ha raggiunto countDown. Questo assicura che siano entrambi in partenza, ma si potrebbe smettere di correre subito dopo. –

+0

@Peter Lawrey: Sì, questo è ciò che intendevo per "non hai alcuna garanzia, tuttavia, come il codice dopo il latch verrà effettivamente eseguito". Tutto ciò che puoi far rispettare è un ordine rigoroso, se lo vuoi. – Thilo

8

Purtroppo, non v'è alcun modo per iniziare due fili contemporaneamente.

Lasciatemi spiegare meglio: prima di tutto, la sequenza t1.Start(); e t2.Start(); viene eseguita con t1 prima e, successivamente, t2. Significa solo che il thread t1 è programmato prima di thread 2, non effettivamente avviato. I due metodi prendono frazioni di secondo ciascuno, quindi il fatto che siano in sequenza non può essere visto da un osservatore umano.

Altro, thread Java sono pianificato, vale a dire. assegnato per essere eventualmente eseguito. Anche se si dispone di una CPU multi-core, non si è sicuri che 1) i thread vengano eseguiti in parallelo (altri processi di sistema potrebbero interferire) e 2) i thread iniziano entrambi subito dopo aver chiamato il metodo Start().

+1

Non è possibile avviare due thread contemporaneamente, ma è possibile eseguire la sincronizzazione nel metodo di esecuzione. Naturalmente, tutto ciò che hai detto sull'eventuale esecuzione si applica ancora. Ma almeno puoi coordinare la sequenza in cui vengono eseguiti i metodi di esecuzione, nel caso ci sia qualche interdipendenza. – Thilo

+0

Quando si ha a che fare con thread e/o più CPU, non esiste realmente "allo stesso tempo". Devi chiarire la tua domanda. – EJP

1

Stanno iniziando da "vicino" alla stessa ora. Il punto è che il tuo codice non sta bloccando allo t1.start().

Potrebbe essere possibile vedere ciò aggiungendo un'istruzione di stampa nella parte superiore del metodo run() della classe Meeting e un'altra istruzione di stampa subito dopo t2.start(). Qualcosa di simile a questo:

public class Meeting implements Runnable { 
    private String name; 
    public Meeting(String name) { 
     this.name = name; 
    } 
    public void run() { 
     System.out.println(name + " is running"); 
    } 
} 

public class Test { 
    public static void main(String[] args) { 
     Meeting m_1 = new Meeting("meeting 1"); 
     Meeting m_2 = new Meeting("meeting 2") 
     Thread t1 = new Thread(m_1); 
     Thread t2 = new Thread(m_2) 
     t1.start(); 
     t2.start(); 
     System.out.println("this might print first!"); 
    } 
} 

// possible output: 
> this might print first! 
> meeting 1 is running 
> meeting 2 is running 
Problemi correlati