Java send message to thread

What is the best way to pass information between threads?

I want to be listening to a server while my program is doing other things, when a message is received from the server I want to interpret it. I know about threading but not sure completely on how it works. If I have a thread listening for the server how can I pass that data to the main thread for interpretation? What is the best way for the main thread to send data to the server? What is the use of the synchronized modifier?

3 Answers 3

If I have a thread listening for the server how can I pass that data to the main thread for interpretation? What is the best way for the main thread to send data to the server?

I’d use a BlockingQueue for this. You define a single BlockingQueue such as the LinkedBlockingQueue . Your listener class then calls queue.take() which will wait for your server to call queue.put() . It leaves all of the synchronization, waits, notifies, etc. to the Java class instead of your own code.

What is the use of the synchronized modifier?

I’d do some reading to understand more about this. This is not the sort of thing that can be answered in a short-ish SO response. The Java concurrency tutorial is a good place to start.

If the server is remote I should be listening on the socket on a new thread. Then when a message is received add it to the queue. Then have the main program check the queue and decide how to interpret the received message. Correct?

Читайте также:  Mikrotik css crs отличия

Something like that should work. Or you can use RMI to put the message in the remote queue. That removes the need to do the socket code. See: oracle.com/technetwork/java/javase/tech/index-jsp-136424.html

If you want synchronous communication between a main thread and a processing thread, you can use a SynchronousQueue.

The idea is that the main thread passes data to the processing thread by calling put() , and the processing thread calls take() . Both are blocking operations.

Note that if you want to send back a result, then things may get a bit more complex as the main thread has to know when the result is ready. A CountDownLatch is a good primitive for this. You can do something like this.

First let’s define a datastructure to pass data around:

public class MethodCall < public final String methodName; public final Object[] args; public final CountDownLatch resultReady; public Object result; public MethodCall(String methodName, Object[] args) < this.methodName = methodName; this.args = args; this.resultReady = new CountDownLatch(1); >public void setResult(Object result) < this.result = result; resultReady.countDown(); >public Object getResult() throws InterruptedException < resultReady.await(); return result; >> 

Define the queue to pass data around, visible by both threads:

public SynchronousQueue methodCalls = new SynchronousQueue(); 

To make a call from the main thread to the processing thread and wait for the result:

MethodCall call = new MethodCall(methodName, args); methodCalls.put(call); Object result = call.getResult(); 

In the processing thread, for instance in a run() method, you can then do:

Where processStuff implements your logic. Of course you should deal with exceptions as well, deal with exit cases, change MethodCall to have more specific things than methodName and args and an Object return, etc.

Источник

Java send message thread

I wrote a game in Java with a client and server side using sockets and data input/output streams. The server side sometimes needs to send a message to all users in a «for» loop, but since writing to a socket can block I created a thread for each user that sends him messages (as well as another thread for each user that listens to incoming messages). The sending thread is built on this idea:

private ArrayList messages = new ArrayList(), newMessages = new ArrayList(); public void run() < while (true) < for (Object message: messages) < try < if (message instanceof Byte) out.writeByte((Byte)message); else if (message instanceof Boolean) out.writeBoolean((Boolean)message); else if (message instanceof String) out.writeUTF((String)message); else if (message instanceof Integer) out.writeInt((Integer)message); else if (message instanceof Long) out.writeLong((Long)message); >catch (IOException e) <> > synchronized (newMessages) < messages.clear(); messages.addAll(newMessages); newMessages.clear(); >> > public void write(Object message) < synchronized (newMessages) < newMessages.add(message); >> 

Unfortunately the run() method is constantly running, so I’d like to insert a sleep command, to achieve something like this:

private ArrayList messages = new ArrayList(), newMessages = new ArrayList(); public void run() < while (true) < try < if (messages.isEmpty() && newMessages.isEmpty()) sleep(0); >catch (InterruptedException e) <> for (Object message: messages) < try < if (message instanceof Byte) out.writeByte((Byte)message); else if (message instanceof Boolean) out.writeBoolean((Boolean)message); else if (message instanceof String) out.writeUTF((String)message); else if (message instanceof Integer) out.writeInt((Integer)message); else if (message instanceof Long) out.writeLong((Long)message); >catch (IOException e) <> > synchronized (newMessages) < messages.clear(); messages.addAll(newMessages); newMessages.clear(); >> > public void write(Object message) < synchronized (newMessages) < newMessages.add(message); interrupt(); >> 

But this may cause the thread to go to sleep when there are messages to send, for example when the write() method is called just after the run() method made the isEmpty() check, that returned true, but has not yet started to sleep. I really can’t think of a way to avoid this problem with sleep(0), has anyone got a idea? Or am I going the wrong way about this? Thanks a bunch.

Источник

Send message to UI thread

I create a thread to listening the input stream of the serial port. And when there is input data coming, I want to send a message to UI thread. Before doing my task, I try to send message from the thread with interval 5000 ms, and send a message to UI thread and Toast it. From the log, I know that the thread is created and running succefully, but the number is not toasted in the UI thread. I think it may be due to fail to send a message from the thread to UI thread, or fail to handle the message in the MessageQueue of UI thread. What’s wrong with my code? Many thanks! MainActivity.java:

public class MainActivity extends Activity < . @Override protected void onCreate(Bundle savedInstancesState) < . setMessageProcessor(); SerialPortListener.start(); >private void setMessageProcessor() < new Handler(Looper.getMainLooper()) < public void handleMessage(Message msg) < Toast.makeText(MainActivity.this, "Message: " + msg.obj.toString(), Toast.LENGTH_SHORT).show(); >>; > > 
public class SerialPortListener < . private static int testNumber = 1; public static void start() < . Thread thread = new Thread(new Runnable() < @Override public void run() < while (true) < Message msg = new Message(); msg.obj = testNumber++; new Handler(Looper.getMainLooper()).sendMessage(msg); Log.i("TEST", "TEST); try < Thread.sleep(5000); >catche(Exception e) < . >> > >); thread.start(); > > 

1 Answer 1

It’s because you are creating a second Handler bound to the main thread from within your «reader thread». Don’t use an anonymous object for the handler in the main thread, make it a member field. Then in your reader thread, send the Message to that specific Handler :

private void setMessageProcessor() < mHandler = new Handler() < . >> public class SerialPortListener < . private static int testNumber = 1; public static void start() < . Thread thread = new Thread(new Runnable() < @Override public void run() < while (true) < Message msg = mHandler.obtainMessage(); msg.obj = testNumber++; msg.sendToTarget(); Log.i("TEST", "TEST); . >> > 

So, it means I need declare public static Handler in my main thread? Is it possible to declare it with private Handler ?

As long as SerialPortListener is an inner class of your Activity , then it’s fine. A better approach (since I now see you had them in separate files) would be to pass the Handler to your SerialPortListener when you create it.

Источник

Get and send messages with Java Threads

I want to make a thread, which runs, computes something with the data i give it, and returns a few values, or an object. The thread is a part of a Swing GUI. My question: How can I make a method that runs when I make the thread, and returns an object (or whatever I want it to return)? My code:

private void nextTurn () < // do something if (turn == white) < try < Engine e = new Engine(); // Engine is implemented by runnable e.start(); Move m = e.getBestMove (board); // thread should work, next code should be excecuted immediately >catch (Exception e) <> > // end of Main class > 

This is the first time I am working with Threads, and I know you should avoid them if possible, but I need it this time for my GUI. The info on the Oracle site on Threads did not help me out. I am able to make a program with multiple Threads that runs indefinately, but I can’t make it work with functions.

2 Answers 2

Since this is with a Swing GUI, consider using a SwingWorker object which creates a background thread (all the code run in the doInBackground method), and then can return a final result and/or interim results. Information on how to use this is well documented in the tutorials here:

SwingWorkers have property change support and thus will allow listeners to observe its state (as a SwingWorker.StateValue) via a PropertyChangeListener. This is one way your program can determine that the thread has completed its processing, get the returned result and go from there.

On an unrelated note, this isn’t in your production code is it?:

If so, you will likely want to fix this as ignored exceptions can bite you in the tail big time.

 if (turn == white) < try < final SwingWorkermySwingWorker = new SwingWorker() < @Override protected Move doInBackground() throws Exception < Engine e = new Engine(); // Engine is implemented by runnable e.start(); Move m = e.getBestMove(board); return m; >>; mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() < public void propertyChange(PropertyChangeEvent evt) < if (StateValue.DONE == mySwingWorker.getState()) < try < Move m = mySwingWorker.get(); // TODO: insert code to run on the EDT after move determined >catch (InterruptedException e) < e.printStackTrace(); >catch (ExecutionException e) < e.printStackTrace(); >> > >); mySwingWorker.execute(); > catch (Exception e) < e.printStackTrace(); >> 

Источник

Оцените статью