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.
Related
I'm writing a program that enables UDP communication between a KUKA robot (programmed in java) and a python server running on a PC. The program on the robot needs to run multiple methods concurrently because it needs to listen/receive messages on 3 sockets simultaneously (they all need to be listening for messages at all times).
I first tried this using multi-threading. My main class is DP_UDP_COMM which start running when the robot is started. When starting some initialization between the robot and python server is done to set up the socket connection, after that the communication processes need to be started. An example of 1 of these 'communication' threads is shown below as Thread UDP_COMM:
//DP_UDP_COMM class is the main class that gets started when the robot starts
public class DP_UDP_COMM extends RoboticsAPITask {
//Some code here
//One of the communication processes that needs to run while the DP_UDP_COMM instance is active
public Thread UDP_COMM = new Thread(new Runnable(){
public void run(){
while(running){
_log.info("Thread Started, Waiting for Action");
try {
ReceiveUDP();
_log.info("Buffer received is: "+String.valueOf(receive));
_log.info("Type received is: "+String.valueOf(ByteProcess.getType(receive)));
if(status==0)
processPacket(receive);
} catch (Exception e) {
// TODO Auto-generated catch block
send = createPacketResponse("ERROR: "+e.getMessage());
try {
SendUDP(send);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace(); }
e.printStackTrace();
}
}
}
});
UDP_COMM.start();
//Some code and other methods here
}
This thread tries to receive a UDP message from a socket using ReceiveUDP(). This is a blocking method so it keeps waiting here untill it receives a message. This message is then processed using processPacket(), which is a method that sends a command to the robot determined by the message that was received. After sending the command it starts listening again for new messages. This loops indefinitely when the robot is active.
The other threads are very similar but use slightly different methods which are bound to different sockets.(For example ReceiveUDPEmergency() which is the same as ReceiveUDP() but with a different socket)
This is working well with one thread, but when running 3 threads concurrently it doesn't work anymore because the threads will wait for each other to complete before looping because ReceiveUDP() is a blocking method.
The solution for this (I think) is to use multi-processing instead of multi-threading because this truly runs them in parallel instead of sequentially.
However when looking at the java.lang.Process documentation I really don't get how creating a process works. In every example they create/start a process from an external .exe file or something like that.
Is it possible to create multiple processes that run multiple methods in parallel within my DP_UDP_COMM instance? How would I do this?
//What have I tried:
As explained above I tried multi-threading at first. But this isn't good enough.
With multi-processing it is not clear how to start a process which just runs a method in parallel to the main instance.
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 currently have the following problem:
I have made a 'Cache Updater Thread', which checks for updates and then sleeps for some amount of time. I have also build a Button, which enables the user to check for updates manually. The Thread is built like this:
public static Thread cacheUpdater = new Thread(new Runnable() {
int milliSecondSleepTime = 10000;
public void run() {
try {
cacheUpdater.setPriority(Thread.MIN_PRIORITY);
//Infinite loop
while (!terminate) {
syncStatus.set(0);
//Check for updates with some methods, not important here.
syncStatus.set(1);
Thread.sleep(this.milliSecondSleepTime);
}
}
catch (InterruptedException e) {
//First check if it is termination time
if (!terminate) {
syncStatus.set(0);
this.run();
}
}
catch (Exception e) {
System.out.println(e);
}
return;
}
});
If the user clicks the manual-update button, the following code is being runned:
#FXML public void syncOnRequest() {
//Only call interrupt, because then it will start again when terminate is still false
CacheManager.cacheUpdater.interrupt();
System.out.println(CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING));
while (!CacheManager.cacheUpdater.getState().equals(State.TIMED_WAITING)) {
//LOOP FOREVER
}
//Some code that needs to be executed after the cache is updated
}
I would like to continue executing code in the syncOnRequest() method, when the cache updater is ready with its manual update. I had the idea to check if it is sleeping, but this is not working, because the System.out.println() immediately returns true. I have measured the time it takes to do the update, and its between 200 and 400 ms.
What am I doing wrong here? And why is it always returning true?
Additional question: sometimes a click on the button just kills the Thread, because it just woke up. The InterruptedException is not thrown.
How can I make sure the Thread will also restart in that case?
Note that Thread#interrupt() is the only polite way to ask your thread to interrupt itself (unless you explicitly implement another). Using it to restart the check is therefore a bad practice. So is checking the thread state for synchronization purposes and exposing the thread that keeps your cache up-to-date to external clients.
You manager should have a updateCache() method you will call directly from UI code and auto-update thread will call the same method periodically*. In that method, make sure that access to your cached data is either correctly synchronized or it happens atomically.
*) Instead of implementing your own periodic thread, consider using
Timer and TimerTask classes as well as making it a daemon thread.
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.
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