24

I have a thread, A which has a list. List holds some objects. Now I want to design a mechanisim by which I can send some message to thread A.

Thread A runs in a loop (it does not wait or sleep). Some other thread, B, sends some message to thread A and thread A empties all its queues.

How can I send messages between threads?

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.
        }
    }
}

EDIT: Can I do it like this?

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
        }
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
akshay
  • 5,235
  • 14
  • 39
  • 49
  • 4
    In Java you usually don't send messages between threads, but you use synchronized objects to pass values between threads. – toto2 Aug 02 '11 at 18:06
  • I synchronized instance variables as methoied in my new edit, will it work? – akshay Aug 02 '11 at 18:20
  • 1
    @akshay You edit looks OK (except you meant `if (getFlag() == true)`). – toto2 Aug 02 '11 at 18:43

3 Answers3

43

You could have a BlockingQueue of message objects. Other threads would place messages onto the queue. As part of the while(true) loop, thread A would poll the queue and process any messages that have arrived.

In code:

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

Other threads can now call queue.put() to send messages to thread A.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • queue is a instance variable of thread A.Now if Thread B will add some values in it at the time when thread A is retrieving it.will it not be a problem? – akshay Aug 02 '11 at 18:14
  • 1
    @akshay: (1) `queue` doesn't have to be a member of `A` (I made it so simply as an illustration); (2) `BlockingQueue` is thread-safe, so either way there won't be a problem. – NPE Aug 02 '11 at 18:16
  • @NPE Should `queue` variable be marked as `volatile` as it is updated from other threads? – abalcerek Feb 21 '17 at 22:17
  • @abalcerek I would say `queue` should probably be final but definitely not volatile. The queue itself is not being regularly replaced, and it is not a primitive value that is being regularly changed. It is always a reference to the same object, so there's no need to load that reference from main memory every time it's needed. – Theodore Murdock Jul 28 '17 at 01:01
  • Can you explain why its important that this queue need to be blocking? – Ring Apr 23 '19 at 02:42
  • Isn't `take()` more suited to this use case than `poll()`? Since `take()` is blocking, you don't need the `null` check. – Nom1fan Feb 01 '20 at 08:31
  • What's being done is achievable using a thread pool with a single thread configured (using newSingleThreadExecutor ). However, the queue is passed Runnable objects and not some MessageType instance, but this can be handled by having the Runnable object hold the variable to be processed. – Basil Musa Jul 23 '20 at 19:59
1

In a simplistic case you can add some instance variable to thread A class and have thread B set its value to indicate that thread A must clear its' queues. In more advanced case you can use some queue of messages that both threads A and B can access. B would place a message there and A would read and act on it.

In all cases, access to variable or queue must be properly guarded for multiple threads access.

Alex Gitelman
  • 24,429
  • 7
  • 52
  • 49
1

You should be able to add a method to class "A" that can be called elsewhere in your code. Just keep the reference to your instance of class "A" in an accessible place.

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
  } 
}
Garvin
  • 477
  • 2
  • 10
  • Will cause problem.As my for loop heavily uses objs , if its cleared suddently it will cause problem – akshay Aug 02 '11 at 18:23
  • 2
    Your question had to do with how do you send a message to thread A so it can perform a desired action. My response was targeted directly at that. Did not go into thread safety as I assume you would be doing the appropriate checks (synchronization) in your code before clearing or reading anything. – Garvin Aug 02 '11 at 18:36