I have a question for you.
I have multiple Threads runnings of a class called ServerThread. When an specific event happens on ANY of those threads, I want to call a method of every other thread running in parallel.
public class ServerThread implements Runnable {
private TCPsocket clientSocket;
public ServerThread(Socket comSocket){
clientSocket = new TCPsocket(comSocket);
}
#Override
public void run(){
boolean waiting = true;
Message msg;
try{
while(waiting){
msg = clientSocket.getMessage();
shareMessage(msg);
}
}catch(Exception e){
ErrorLogger.toFile("EndConnection", e.toString());
}
}
public void shareMessage(Message msg){
clientSocket.sendMessage(msg);
}
}
I am talking about this specific line
shareMessage(msg);
which I would like to be called on every thread/instance
-- so that a message is sent to every client (in all tcp connections)
I've tried with synchronized but either I'm not using it well or that is not what I am looking for.
Another thing that might work is keeping a class with an static member which is a list of those tcpconnection objects and then do some loop in all every time.
Thanks for your help and time.
Edited with one possible solution
*Add an static array as a member of the class and add/remove objects of same class (or tcp sockets would also work)
private static ArrayList<ServerThread> handler;
...
handler.add(this);
...
handler.remove(this); //when client exists and thread stops
*Then create a method that iterates for each connection, and make it synchronized so that two threads won't interact at the same time. You may want to implement synchronized on your message sending methods as well.
public void shareMessage(Message msg){
//this.clientSocket.sendMessage(msg);
synchronized (handler){
for(ServerThread connection: handler){
try{
connection.clientSocket.sendMessage(msg);
} catch(Exception e){
connection.clientSocket.closeConnection();
}
}
}
}
First: synchronized is required to prevent race conditions when multiple threads want to call the same method and this method accesses/modifies shared data. So maybe (probably) you will need it somewhere but it does not provide you the functionality you require.
Second: You cannot command an other thread to call a method directly. It is not possible e.g. for ThreadA to call methodX in ThreadB.
I guess you have one thread per client. Probably each thread will block at clientSocket.getMessage() until the client sends a message. I don't know the implementation of TCPsocket but maybe it is possible to interrupt the thread. In this case you may need to catch a InterruptedException and ask some central data structure if the interrupt was caused because of a new shared message and to return the shared message.
Maybe it is also possible for TCPsocket.getMessage() to return, if no message was received for some time, in which case you would again have to ask a central data structure if there is a new shared message.
Maybe it is also possible to store all client connections in such a data structure and loop them every time, as you suggested. But keep in mind that the client might send a message at any time, maybe even at the exact same time when you try to send it the shared message received from another client. This might be no problem but this depends on your application. Also you have to consider that the message will also be shared with the client that sent it to your server in the first place…
Also take a look at java.util.concurrent and its subpackages, it is likely you find something useful there… ;-)
To summarize: There are many possibilities. Which one is the best depends on what you need. Please add some more detail to your question if you need more specific help.
Related
Maybe I'm thinking to complicated, but I have the following situation:
I have a class Server.java extending Thread with the following relevant part of the code:
public void run() {
while(listening) {
try {
ServerThread cst = new ServerThread(serverSocket.accept());
cst.start();
} catch (IOException e) {
listening = false;
System.out.println(e.getMessage());
}
}
}
My ServerThread then handles all the incoming stuff.
My question now is, if there is any possibility to stop this Thread (Server) like for example over the command line.
I tried to add a new class, that would handle command line input and .interrupt() this Thread, but that kinda just made a big mess..
Here's one way:
Provide a setter for listening that can be accessed from another class/thread.
Set a reasonable timeout (say, 1 sec) on the ServerSocket and handle the SocketTimeoutException.
To stop the thread, set listening to false and within 1 second the thread will stop. If you want finer control, investigate the async I/O classes in java.nio.
You can define listening as volatile, with a setter and set that to false from another class whenever you want to stop the Thread.
I have program (MAIN) that has two thread that communicates with com port (COM) and TCP session (TCP).
If main (MAIN) program need info from TCP and COM modules it sends request message R (tR and cR). When threads have answer they send back answer A (tA and cA). I have problem, when I send reguest to COM (cR) and without getting answer from it have answer from TCP- tA. COM R-A should be somehow isolated from TCP interruption. How to solve this problem using JAVA 1.4 ?
UPD. On tA event MAIN initiates cR - request to COM port. Main can initiate request to COM by itself. I would like avoid to have second question to COM port without getting answer from first one.
UPD2. Actually whole system looks like picture below. cR might be started by tA or by uR. And cA can answer to TCP via tR or to UI via uA.
Following scenarios are correct
uR->cR->cA->tR-tA->cR->cA->uA
cA->tR->tA->cR
uR->cR->cA->uA
I'm getting troubles when two requests goes to COM at the same time.
cA->tR->tA->cR
uR->cR
I would like to allow new request only in case when COM returns answer to first caller.
As I understand correctly you have 2 threads in main method. 1 thread is interacting with with TCP and another with COM. Right?
If this is the case than what you can do is you can let handle thread 1 to handle all TCP request/response and thread 2 to handle all COM request/response. And the main thread is not aware of this. Until the time both thread finish their job independently the main threads wait and once both thread are done with their job, Main thread can resume its work. hence the communication of COM and TCP is completley separate. you can use Threads "join()" method here.
Did I answer your question?
You don't have to use multiple threads. Just read the request from the socket, synchronously process the request by communicating over the COM port, and then write the response over the socket.
There may be reasons to use multiple threads, though. For example, perhaps you want to be able to respond to socket requests with a time-out error if the COM port doesn't respond fast enough, but the serial port library you are using doesn't support a time-out configuration. In that case, you'll have to clarify your requirements. What do you want to happen if another request is received from the socket, but the COM thread is still stuck handling a previous request? You could wait, respond with an error immediately, etc.
Create a single-thread ExecutorService. Whenever you need to interact with the COM port, whether the request originates from the socket or from the main program itself, submit the task to this service. This will ensure that serial communications won't be interleaved with competing requests.
The basic idea here is to allow only one thread to use the COM port, consuming a queue of tasks produced by various other threads.
Here is one example that can explain your system. Here i have made a environment of caller receiver. Until caller not end with his or her statement receiver can not start with saying anything or respond to caller.
Caller.java
public class Caller implements Runnable {
MaintainACall call;
Caller(MaintainACall me)
{
call=me;
new Thread(this,"Mr X").start();
}
public void run()
{
String a[]={"Hello how r u", "I'm in vadodara"};
for(int i=0;i<2;i++)
{
call.sayHello(a[i]);
}
}
}
Receiver.java
public class Reciver implements Runnable {
MaintainACall call;
Reciver(MaintainACall call)
{
this.call=call;
new Thread(this,"Mr Y").start();
}
public void run()
{
call.Wtshesay();
}
}
MaintainACall.java
public class MaintainACall {
String say;
boolean valueSet=false;
synchronized String Wtshesay()
{
while(!valueSet)
try
{
wait();
}
catch(InterruptedException ie)
{
System.out.println(ie);
}
System.out.println("I have heared "+say);
valueSet=false;
notify();
return say;
}
synchronized void sayHello(String msg)
{
while(valueSet)
try
{
wait();
}
catch(InterruptedException ie)
{
System.out.println(ie);
}
say=msg;
valueSet=true;
System.out.println("She says "+say);
notify();
}
}
MainClass.java
public class MainClass {
public static void main(String arg[])
{
MaintainACall my=new MaintainACall();
new Caller(my);
new Reciver(my);
}
}
I haven't got any code at the moment but I have a situation where I will be implementing an Java application onto a wireless sensor. There can only be one main method.
There will be multiple other wireless sensors that can connect to my sensor. My sensor needs to do a calculation based on thhe information provided to me by the other sensors. Each sensor can choose whether or not they want to participate in the calculation. Every 1 second, my sensor does a calculation.
So basically, what I need is to listen for incoming sensors, provide them with a thread to interact with, and retrieve the information from each sensor.
My question is, in my application, how do I listen for incoming sensors (blocking call) and also free my application to carry out its calculations?
From a high level, this is what your application will do
==Main Thread==
start socket
Start processing thread
accept an incoming connection (this will cause the thread to block until a connection occurs)
start new thread to handle socket (handler thread) (alternatively use a thread pool, but that is more complicated)
return to 3
==Handler Thread==
Receive open socket from main thread
Save data coming in from socket to be given to processing thread
Finish and close socket
==Processing Thread==
Wait 1 second
Process data retrieved from step 2 of Handler Thread
Return to 1
You need another thread that receives the information of all the communication threads. You should look at the utilities in java.util.concurrent such a BlockingQueue that let threads pass data to one another thread-safely.
Most of all you should read a lot about multi-threading: it is not a trivial topic.
This will get you started. Add error/exception checking/handling as necessary.
public class Test {
static class WorkTask42 implements Runnable {
public void run() {
// background work
}
}
public static void main(String... args) throws Exception {
// repeat for each background task
WorkTask42 wt = new WorkTask42();
Thread a = new Thread(wt);
a.setDeamon(true);
a.start();
}
}
How does async JMS work? I've below sample code:
public class JmsAdapter implements MessageListener, ExceptionListener
{
private ConnectionFactory connFactory = null;
private Connection conn = null;
private Session session = null;
public void receiveMessages()
{
try
{
this.session = this.conn.createSession(true, Session.SESSION_TRANSACTED);
this.conn.setExceptionListener(this);
Destination destination = this.session.createQueue("SOME_QUEUE_NAME");
this.consumer = this.session.createConsumer(destination);
this.consumer.setMessageListener(this);
this.conn.start();
}
catch (JMSException e)
{
//Handle JMS Exceptions Here
}
}
#Override
public void onMessage(Message message)
{
try
{
//Do Message Processing Here
//Message sucessfully processed... Go ahead and commit the transaction.
this.session.commit();
}
catch(SomeApplicationException e)
{
//Message processing failed.
//Do whatever you need to do here for the exception.
//NOTE: You may need to check the redelivery count of this message first
//and just commit it after it fails a predefined number of times (Make sure you
//store it somewhere if you don't want to lose it). This way you're process isn't
//handling the same failed message over and over again.
this.session.rollback()
}
}
}
But I'm new to Java & JMS. I'll probably consume messages in onMessage method. But I don't know how does it work exactly.
Do I need to add main method in JmsAdapter class? After adding main method, do I need to create a jar & then run the jar as "java -jar abc.jar"?
Any help is much appreciated.
UPDATE: What I want to know is that if I add main method, should I simply call receiveMessages() in main? And then after running, will the listener keep on running? And if there are messages, will it retrieve automatically in onMessage method?
Also, if the listener is continuously listening, doesn't it take CPU??? In case of threads, when we create a thread & put it in sleep, the CPU utilization is zero, how doe it work in case of listener?
Note: I've only Tomcat server & I'll not be using any jms server. I'm not sure if listener needs any specific jms server such as JBoss? But in any case, please assume that I'll not be having anything except tomcat.
Thanks!
You need to learn to walk before you start trying to run.
Read / do a tutorial on Java programming. This should explain (among other things) how to compile and run a Java program from the command line.
Read / do a tutorial on JMS.
Read the Oracle material on how to create an executable JAR file.
Figure out what it is you are trying to do ... and design your application.
Looking at what you've shown and told us:
You could add a main method to that class, but to make an executable JAR file, you've got to create your JAR file with a manifest entry that specifies the name of the class with the main method.
There's a lot more that you have to do before that code will work:
add code to (at least) log the exceptions that you are catching
add code to process the messages
add code to initialize the connection factory and connection objects
And like I said above, you probably need some kind of design ... so that you don't end up with everything in a "kitchen sink" class.
if I add main method, should I simply call receiveMessages() in main?
That is one approach. But like I said, you really need to design your application.
And then after running, will the listener keep on running?
It is not entirely clear. It should keep running as long as the main thread is alive, but it is not immediately obvious what happens when your main method returns. (It depends on whether the JMS threads are created as daemon threads, and that's not specified.)
And if there are messages, will it retrieve automatically in onMessage method?
It would appear that each message is retrieved (read from the socket) before your onMessage method is called.
Also, if the listener is continuously listening, doesn't it take CPU???
Not if it is implemented properly.
In case of threads, when we create a thread & put it in sleep, the CPU utilization is zero, how doe it work in case of listener?
At a certain level, a listener thread will make a system call that waits for data to arrive on a network socket. I don't know how it is exactly implemented, but this could be as simple as an read() call on the network socket's InoutStream. No CPU is used by a thread while it waits in a blocking system call.
This link looks like a pretty good place with examples using Oracle AQ. There's an examples section that tells you how to setup the examples and run them. Hopefully this can help.
Link to Oracle Advanced Queueing
This question has no doubt been asked in various forms in the past, but not so much for a specific scenario.
What is the most correct way to stop a Thread that is blocking while waiting to receive a network message over UDP.
For example, say I have the following Thread:
public class ClientDiscoveryEngine extends Thread {
private final int PORT;
public ClientDiscoveryEngine(final int portNumber) {
PORT = portNumber;
}
#Override
public void run() {
try {
socket = new DatagramSocket(RECEIVE_PORT);
while (true) {
final byte[] data = new byte[256];
final DatagramPacket packet = new DatagramPacket(data, data.length);
socket.receive(packet);
}
} catch (SocketException e) {
// do stuff 1
} catch (IOException e) {
// do stuff 2
}
}
}
Now, would the more correct way be using the interrupt() method? For example adding the following method:
#Override
public void interrupt() {
super.interrupt();
// flip some state?
}
My only concern is, is socket.receive() not a non-interruptable blocking method? The one way that I have thought of would be to implement the interrupt method as above, in that method call socket.close() and then cater for it in the run method in the catch for the SocketException. Or maybe instead of while(true) use some state that gets flipped in the interrupt method. Is this the best way? Or is there a more elegant way?
Thanks
The receive method doesn't seem to be interruptible. You could close the socket: the javadoc says:
Any thread currently blocked in receive(java.net.DatagramPacket) upon
this socket will throw a SocketException
You could also use setSoTimeout to make the receive method block only for a small amount of time. After the method has returned, your thread can check if it has been interrupted, and retry to receive again for this small amount of time.
Read this answer Interrupting a thread that waits on a blocking action?
To stop a thread, you should not user neither interrupt nor stop in java. The best way, as you suggested by the end of your question, is to have the loop inside the main method controlled by a flag that you can rise as needed.
Here is an old link about this :
http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
Other ways of stopping a thread are deprecated and don't provide as much control as this one. Also, this may have changed a bit with executor services, I didn't have time to learn much about it yet.
Also, if you want to avoid your thread to be blocked in some IO state, waiting for a socket, you should give your socket a connection and reading time out (method setSoTimeout).
Regards,
Stéphane
This is one of the easier ones. If it's blocked on a UDP socket, send the socket a UDP message that instructs the receiving thread to 'stop'.
Rgds,
Martin