Since thread.stop() is deprecated in Java, what is the proper way to deal with blocking waits that are never going to finish?
For example, when running a server-client model with many clients, my server code may look like:
new Thread(){
#Override
public void run(){
while(accept){
try {
/* attempt to read a single message */
ObjectInputStream is = new ObjectInputStream(s.getInputStream());
Message m = (Message) is.readObject();
/* delegate message to appropriate handler */
MessageDelegator.getInstance().delegate(m);
} catch (IOException | ClassNotFoundException ex) {
}
}
}
}.start();
However, the listening process here is blocking, so the classical trick of setting accept=false; will not work here (a client may perpetually not send anything, resulting in a perpetually hanging thread). How can I kill this thread if I'm no longer allowed to use thread.stop()?
You're looking for thread.interrupt().
Related
I am actually using sockets listeners in a Java program.
The idea is to let my program run until it catches an external event. As soon as it catches it, I have to update my layout.
In order to let my application run while it was listening on a specific port, I did something like this :
// new thread allows me to let my program continue
new Thread() {
public void run() {
try {
while (true) {
try (ServerSocket listener = new ServerSocket(59090)) {
System.out.println("The server is running...");
// listening
while (true) {
try (Socket socket = listener.accept()) {
// catches event
System.out.println("event caught");
InputStream raw = socket.getInputStream();
headerData = getHeaders(raw);
// some code
// ...
// ...
// Update UI
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
The idea is that I constantly listen on the port 59090 and I execute my specific code once I use that port and that works well.
The problem now is when I catch an event.
It seems that I can't act on the UI if I am not in the "main" Thread. Am I right ?
Is it possible to send an information to my "main thread" in order to tell it to update UI ? Otherwise is it possible to "switch" my main thread to this one ?
EDIT:
I've seen that in Android you could use AsyncTask and the method onPostExecute() allows to send informations to the UI thread.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
Is there an equivalent in Java?
Thank you
I face this problem in Java.
I have a server class named MyServer and I want to implement a thread pool where each thread runs a method of MyServer when a request comes. I have created another class that implements a server pool named MultiThreadedSocketServer. The class is this:
public class MultiThreadedSocketServer {
public void startServer(MyServer s, int localport, int threadPoolSize) {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(threadPoolSize);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(localport);
System.out.println("Waiting for clients to connect...");
while (true) {
Socket clientSocket = serverSocket.accept();
clientProcessingPool.submit(new ClientTask(clientSocket, s));
}
} catch (IOException e) {
System.err.println("Unable to process client request");
e.printStackTrace();
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
}
the class named MultiThreadedSocketServer has an argument named Server s which passes it in client Task class which a thread is created. The client task class is this:
class ClientTask implements Runnable {
private final Socket clientSocket;
private MyServer s;
public ClientTask(Socket clientSocket, MyServer s) {
this.s = s;
this.clientSocket = clientSocket;
}
#Override
public void run() {
System.out.println("Got a client !");
String inputLine = null;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Do whatever required to process the client's request
inputLine = in.readLine();
if (inputLine.equals("Bye")) {
System.out.println("Bye");
System.exit(0);
}
s.handleRequest(inputLine);
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
As you can see when a request comes the handleRequest method of class MyServer is invoked. I want to make this method to run synchronized, meaning only one thread at a time to be able to run this method. Adding synchronized before the method implementation does not achieve anything.
Can anybody give me the proper way to do this?
Thanks in advance for your time.
PS: I added the whole code
MyServer Class
http://pastebin.com/6i2bn5jj
Multithreaded server Class
http://pastebin.com/hzfLJbCS
As it is evident in main I create three requests with handleRequest with arguments Task, task2 and Bye.
The correct output would be
Waiting for clients to connect...
Got a client !
This is an input Task
Request for Task
Got a client !
This is an input task2
Request for task2
Got a client !
This is an input
Bye
But Instead the order is mixed. Sometimes Bye which shuts the server can be executed first. I want to ensure that the order is the one where the requests are created in the main.
But Instead the order is mixed. Sometimes Bye which shuts the server can be executed first. I want to ensure that the order is the one where the requests are created in the main.
You say that you want the server to handle requests in order. This is hard to ensure because you are opening up 3 sockets and writing them to the server but not waiting for any response. This is implementation dependent but I'm not sure there is any guarantee that when the client returns from doing a socket InputStream write, that the server has received the bytes. This means that from the client side, there is no guarantee that the IO completes in the order that you want.
To see if this is the problem, I would remove the System.exit(0) to see if the other lines make it, just after the "Bye" string does. Or you could put a Thread.sleep(5000); before the exit(0).
A simple sort-of fix would be to make sure your PrintStream has auto-flush turned on. That at least will call flush on the socket but even then there are race conditions between the client and the server. If the auto-flush doesn't work then I'd have your client wait for a response from the server. So then the first client would write the first command and wait for the acknowledgement before going to the 2nd command.
In terms of your original question, locking on the server wouldn't help because of the race conditions. The "Bye" might make it first and lock the server fine.
These sorts of questions around how to synchronize the threads in a multi-threaded program really make no sense to me. The whole point of threads is that they run asynchronously in parallel and don't have to operate in any particular order. The more that you force your program to spit out the output in a particular order, the more you are arguing for writing this without any threads.
Hope this helps.
If the problem is that the bye message kills the server before other requests can be handled, one solution could be to not call System.exit(0); on bye.
The bye message could set a flag block further requests from being handled and also notify some other mechanism to call System.exit(0); when the thread pool is idle with no requests left to handle.
Would it be appropriate to use a thread to get objects received by a socket's InputStream and then add them to a ConcurrentLinkedQueue so that they can be accessed from the main thread without blocking at the poll-input loop?
private Queue<Packet> packetQueue = new ConcurrentLinkedQueue<Packet>();
private ObjectInputStream fromServer; //this is the input stream of the server
public void startListening()
{
Thread listeningThread = new Thread()
{
public void run()
{
while(isConnected()) //check if the socket is connected to anything
{
try {
packetQueue.offer((Packet) fromServer.readObject()); //add packet to queue
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
listeningThread.start(); //start the thread
}
public Packet getNextPacket()
{
return packetQueue.poll(); //get the next packet in the queue
}
It depends on what you need to do with this object that you'll use in main thread.
If need sometime to process it or if it'll be used many times than you can put it in a queue or in another class that will hold this object for you, but if the time you need to process it is low you and you don't need this object further after processing you don't really need to use a queue.
About using the ConcurrentQueue depends too, you need order? you need guarantee synchronism between the read and the write?
You can use Asynchronous socket too to handle many clients and process in the same thread or even getting the objects from them and throwing in a queue to further process.
But "be appropriate" is hard to answer because depends on what you need to do with this objects and how you'll handle it.
I'm writing an android app in java and I want to create a listener that receive messages in a while(true) loop, and also to be able to send messages to the server.
For this task I'm using sockets with asyncTask.
I have written a connectionHandler class which handle all the send and receive requests for my app.
So far so good, everything is working fluently for just sending and receiving messages one at a time, but I just couldn't find a way to do it simultaneously.
I need to execute the following code in a thread, but I don't know how to do it, because I have to return a String:
public static String receive() {
try {
return mConnectionHandler.new AsyncReceiveFromServer().execute()
.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
private class AsyncReceiveFromServer extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
String result = null;
try {
result = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
When I'm running the receive function in a while(true) loop, I can't send messages, because the ...execute().get() is blocking the java class connectionHandler.
So to sum up, how can I execute the above code in a thread or any other asynchronous way?
Or maybe you have any other suggestion to run the send and receive simultaneously while the receive is a while(true) loop?
First off- never use execute.get(). If you think you need to use it, you're architected wrong- it breaks the entire point of using a thread to have the calling thread wait for a result. If you just call execute, you'll run on another thread and work fine. If you need more than 1 thread running truly simultaneously, use executeOnExecutor() to override the 4.0 shared thread pool mechanism of AsyncTask.
Or better yet- don't use AsyncTask for this. You have something you want to run forever, waiting for input from a remote connection. This is a better fit for a Thread than an AsyncTask. I'd go with a thread and have the while loop built into the thread, and have the thread terminate only when the connection is closed.
This is part of a messenger project in java. Because clients use direct connections to chat, I want eavry client to listen on some port, and others to make a socket to that address. but when i call ServerSocket.accept() in another thread it appears that all threads have been suspended. which means nothings happens after executing that command. Here is the code which makes new thread.
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
while(true){
System.out.println("flag1");
Socket socket = listeningSocket.accept();
System.out.println("flag2");
new Chat(socket).setVisible(true);;
jTextArea1.append("successfully connected\n");
}
} catch (NullPointerException e) {
System.out.println("i know");
}
catch (IOException e) {
e.printStackTrace();
jTextArea1.append("error in recieving connection\n");
}
}
});
any ideas how to solve this?
when i call ServerSocket.accept() in another thread it appears that
all threads have been suspended
Appears how? accept() only blocks the current thread. Are you calling it in the AWT thread? e.g. an actionPerformed() method? Don't do any network operations in those methods, use separate threads.
Socket.accept() DOES block the CURRENT thread. You'll see "flag2" printed only after a connection is received. But it blocks only CURRENT thread.
I suspect you are not running the separate thread correctly (you're calling yourThreadHere.start(), not .run(), right?).