Dealing with multithreading in UI - java

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

Related

Read and write from a socket simultaneously

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.

My GUI freezes after I recreate a ServerSocket

My Server is build around support to update the listening socket, by doing so I use the following method. my problem occurs after this method is called for the second time, this is first called at start up from the main method then later it is called by clicking a button in a JFrame. what happens is that the JFrame freezes when this method is called via button, as you can see by the code I tried to make this method run a server in a new thread but it hasn't changed my outcome. Does anyone know how to fix this? or at least what is causing it? also any code after the method is called in the main doesn't get execute, so I believe it is a thread problem. (MiniServer extends Thread and is used to handle each connected client individually)
public static void startListening(final int port)
{
listeningThread = new Thread()
{
public void run()
{
try {
serverSocket = new ServerSocket(port);
while(!stop)
{
boolean loop = true;
while (loop)
{
serverSocket.setSoTimeout(1000);
try{
clientSocket = serverSocket.accept();
loop = false;
} catch (SocketTimeoutException e){
}
}
if(!clientSocket.equals(null))
{
MiniServer mini = new MiniServer(clientSocket);
mini.start();
clientSocket = null;
}
}
} catch (IOException e) {
}
}
};
listeningThread.run();
}
You need to be calling listeningThread.start(), which will create a new thread. Right now, you're just calling the thread's run() method on the current thread. The first time you do that it works, since you're on the main thread. The second time, though, you're on the UI thread, reacting to the button press. This causes your UI thread to block.

Listening for connections in a separate thread

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?).

How to stop ServerSocket Thread correctly? Close Socket failed

I know this has been discussed some times before, but I can't find an appropriate solution for my problem. I want to run a ServerSocket thread in the background, listening to the specified port. It's working actually, but only once. Seems that the port the server is listening to is never closed correctly and still active when I try to restart (O don't restart the thread itself). Can some tell why it is not working correctly? Thanks in advance for any help...!
edit:
I have same problem on the client side. I have a sender thread and also that one cannot not be stopped. What is the best way to do that?
The ClientConnector is just a class which connects to the server port and sends the data.
It's not a thread or anything like that.
That's my sender class:
private class InternalCamSender extends Thread {
private int sendInterval = 500; // default 500 ms
private ClientConnector clientConn = null;
public InternalCamSender() {
this.sendInterval = getSendingInterval();
this.clientConn = new ClientConnector();
}
#Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
clientConn.sendCamPdu(CodingScheme.BER, createNewPDU());
try {
Thread.sleep(sendInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And I try to handle it's behaviour like that:
if(jButton_startSending.getText().equals(STARTSENDING)) {
new Thread() {
public void run() {
iSender = new InternalCamSender();
iSender.start();
jButton_startSending.setText(STOPSENDING);
}
}.start();
} else {
new Thread() {
public void run() {
if(iSender.isAlive()) {
iSender.interrupt();
try {
iSender.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
iSender = null;
jButton_startSending.setText(STARTSENDING);
}
}.start();
}
Somehow I cannot stop the InternalCamSender like that. I tried with a volatile boolean before, was the same. I read the http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html page and tried also the example What should I use instead of Thread.stop? but even that was not stopping the thread? I am lost.
Any ideas?
edit:
found the answer for my clinet sending problem here http://www.petanews.de/code-snippets/java/java-threads-sauber-beenden-ohne-stop/
even i don't know why that is working. I am sure I tried that way before.
Problem solved!
You should close your resources (the streams and socket) in a finally block, rather than a catch block - this way the resources are always closed, whether an exception is caught or not.
It's also a bad practice to call System.exit() from within a catch block or within a thread - you are forcibly shutting down the whole JVM on any instance of an error. This is likely the cause of your problem with the server socket as well - whenever any exception is encountered with reading/closing the streams, you are exiting the JVM before you have a chance to close the server socket.

Using threads and ProcessBuilder

I am really unfamiliar with working with threads, so I was hoping someone could help me figure out the best way to do this.
I have a JButton in my java application...when you click on the button, I have a Process Builder that creates a process which executes some external python code. The python code generates some files, and this can take some time. When the python code is done executing, I need to load those files into an applet within my Java application.
In its current form, I have a p.waitFor() within the code that calls the external python file...so when you click on the button, the button hangs (the entire application hangs actually) until the process is done. Obviously, I want the user to be able to interact with the rest of the application while this process is going on, but as soon as it's done, I want my application to know about it, so that it can load the files into the applet.
What is the best way to do this?
Thanks for your help.
You should use SwingWorker to invoke the Python process on a background thread. This way your UI will remain responsive whilst the long-running task runs.
// Define Action.
Action action = new AbstractAction("Do It") {
public void actionPerformed(ActionEvent e) {
runBackgroundTask();
}
}
// Install Action into JButton.
JButton btn = new JButton(action);
private void runBackgroundTask() {
new SwingWorker<Void, Void>() {
{
// Disable action until task is complete to prevent concurrent tasks.
action.setEnabled(false);
}
// Called on the Swing thread when background task completes.
protected void done() {
action.setEnabled(true);
try {
// No result but calling get() will propagate any exceptions onto Swing thread.
get();
} catch(Exception ex) {
// Handle exception
}
}
// Called on background thread
protected Void doInBackground() throws Exception {
// Add ProcessBuilder code here!
return null; // No result so simply return null.
}
}.execute();
}
You really want to create a new thread for monitoring your new process. As you've discovered, using just one thread for both the UI and monitoring the child process will make the UI seem to hang while the child process runs.
Here's some example code that assumes the existence of a log4j logger which I think will illustrate one possible approach...
Runtime runtime = Runtime.getRuntime();
String[] command = { "myShellCommand", "firstArgument" };
try {
boolean done = false;
int exitValue = 0;
Process proc = runtime.exec(command);
while (!done) {
try {
exitValue = proc.exitValue();
done = true;
} catch (IllegalThreadStateException e) {
// This exception will be thrown only if the process is still running
// because exitValue() will not be a valid method call yet...
logger.info("Process is still running...")
}
}
if (exitValue != 0) {
// Child process exited with non-zero exit code - do something about failure.
logger.info("Deletion failure - exit code " + exitValue);
}
} catch (IOException e) {
// An exception thrown by runtime.exec() which would mean myShellCommand was not
// found in the path or something like that...
logger.info("Deletion failure - error: " + e.getMessage());
}
// If no errors were caught above, the child is now finished with a zero exit code
// Move on happily

Categories

Resources