2011-08-02 9 views
20

Mam wątek, A, który ma listę. Lista zawiera niektóre obiekty. Teraz chcę zaprojektować mechanisim, za pomocą którego mogę wysłać wiadomość do wątku A.Komunikacja między dwoma wątkami

działa w pętli (nie czeka ani nie zasypia). Inny wątek, B, wysyła wiadomość do wątku A, a wątek A opróżnia wszystkie jego kolejki.

Jak mogę wysyłać wiadomości między wątkami?

class A extends Thread { 
    List<Object> objs = something; //Init it 
    void run() { 
     while(true) { 
      //Body which works on objects. 
      //After receiving an external message, "A" should perform some action, for example, empty objects. 
     } 
    } 
} 

EDYCJA: Czy mogę zrobić to w ten sposób?

class A extends Thread { 
    List<Object> objs = something; //Init it 
    Boolean flag = false; 

    public void setFlag(boolean value) { 
     synchronized(flag) { 
      this.flag = value; 
     } 
    } 

    public void getFlag() { 
     synchronized(flag) { 
      return this.flag; 
     } 
    } 

    void run() { 
     while(true) { 
      //Body which works on objects. 
      //After receiving an external message, A should perform some action, for example, empty objects. 
      if (getFlag == true) 
       //Empty list 
     } 
    } 
} 
+3

W Javie zazwyczaj nie wysyła się wiadomości między wątkami, ale do synchronizowania obiektów między wątkami używa się obiektów zsynchronizowanych. – toto2

+0

I zsynchronizowane zmienne instancji, jak meto w mojej nowej edycji, będzie działać? – akshay

+1

@akshay Edycja wygląda OK (poza tym, że chodziło o 'if (getFlag() == true)'). – toto2

Odpowiedz

32

Możesz mieć BlockingQueue obiektów wiadomości. Inne wątki umieszczałyby wiadomości w kolejce. W ramach pętli while(true), wątek A będzie poll kolejki i przetwarzać wszystkie wiadomości, które przybyły.

W kodzie:

class A extends Thread{ 
List<Object> objs = something ;//init it 
BlockingQueue<Message> queue = new LinkedBlockingQueue<Message>(); 
void run(){ 
    while(true){ 
     Message msg; 
     while ((msg = queue.poll()) != null) { 
     // process msg 
     } 
     // do other stuff 
    } 
    } 
} 

Inne wątki mogą teraz zadzwonić queue.put() wysyłać wiadomości do wątku A.

+0

Kolejka jest instancyjną zmienną wątku A. Teraz, jeśli wątek B doda pewne wartości w czasie, gdy wątek A go pobierze. Czy nie będzie to problemem? – akshay

+1

@akshay: (1) 'kolejka' nie musi być członkiem' A' (zrobiłem to po prostu jako ilustracja); (2) 'BlockingQueue' jest wątkowo bezpieczny, więc tak czy inaczej nie będzie problemu. – NPE

+0

: Czy moja nowa edycja rozwiąże problem ?????????? – akshay

0

W uproszczonym przypadku można dodać zmienną instancji do klasy wątku A i mieć wątek B ustawić jego wartość, aby wskazać, że wątek A musi wyczyścić swoje kolejki. W bardziej zaawansowanym przypadku możesz użyć kolejki komunikatów, do których mają dostęp oba wątki A i B. B umieściłby tam wiadomość, a A odczytałby i działał na jej podstawie.

We wszystkich przypadkach dostęp do zmiennej lub kolejki musi być odpowiednio chroniony, aby uzyskać dostęp do wielu wątków.

0

Powinieneś być w stanie dodać metodę do klasy "A", którą można wywołać w innym miejscu kodu. Po prostu zachowaj odwołanie do swojego wystąpienia klasy "A" w dostępnym miejscu.

class A extends Thread{ 
List<Object> objs = something ;//init it 
void run(){ 
    while(true){ 
     //body which works on objs 
     //open receiving external message A should perform some action ie empty objs 
    } 
    } 
    void ChangeState() 
    { 
    //clear objs 
    } 
} 
+0

Wystąpi problem. Ponieważ moja pętla for mocno używa objs, jeśli zostanie wyczyszczona suddently, to spowoduje problem – akshay

+0

Twoje pytanie dotyczyło sposobu wysłania wiadomości do wątku A, aby mógł wykonać żądaną akcję. Moja odpowiedź była skierowana bezpośrednio na to. Nie poszedłem na temat bezpieczeństwa wątków, zakładając, że wykonasz odpowiednie kontrole (synchronizację) w swoim kodzie przed wyczyszczeniem lub odczytaniem czegokolwiek. – Garvin