I'm getting some exception and I need to know when the program closes itself because I need to close the socket.
I have the default public static main method where I'm keep repeating an action and a Thread class.
private static Thread thread;
public static boolean isRunning = true;
public static void main(String[] args){
thread = new Thread(new ThreadListenServer());
thread.start();
Timer timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run(){
// some action
}
}
timer.scheduleAtFixedRate(task, 0, 10000);
isRunning = false;
}
And the thread class which is running in background:
public class ThreadListenServer implements Runnable{
private DatagramSocket socket;
public ThreadListenServer() throws SocketException{
socket = new DatagramSocket(6655);
}
#Override
public void run() {
while(MainProgram.isRunning){
// some action
}
socket.close();
}
}
I don't know why, but isRunning it's becoming false, but it shouldn't. How am I supposed to close the socket if the main program was closed? (It's causing because the Thread still running in the background even if the program was closed).
I was thinking about to create the socket in the main class then I pass the socket object as a parameter to the ThreadClass and if the program is closed, than I should close the socket as well.
Use:
thread.setDaemon(true);
This will shut the thread. It tells the JVM it is a background thread , so it will shut down on exit.
Ill take the assumption you have a JFrame of some sort running as the class MainProgram. You have 2 options
1: set your Jframe to close all threads when it is closed.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
2: add a window listener and manually close your thread (maybe you have to send some information across the socket before you close it)
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// send your socket its close message and shut everything down
System.exit(0);
}
});
To stop all Threads when your program exits cleanly, you'll need to define a termination policy for each Thread that gets started. This is normally done using Interrupts and ExecutorService.shutdownNow() method sends an interrupt to each running thread.
A clean termination policy consists to two parts:
Sending stop signal to thread – aka interrupting it
Designing threads to act on interruption
A thread in Java could be interrupted by calling Thread.interrupt() method. Threads can check for interruption by calling Thread.isInterrupted() method. A good thread must check for interruption at regular intervals, e.g. as a loop condition and checking blocking functions for InterruptedExceptions.
It is important to note that Sockets in Java are oblivious to interruption. For example, if a Thread is blocked on Socket.accept(), it will not throw InterruptedException when the Thread is interrupted. In this case, you need to define a public method which closes the underlying socket by calling Socket.close() forcing the blocking function to throw an Exception (I guess SocketException).
A few things come to mind.
It would appear you are performing a blocking I/O operation using sockets. You may need to interrupt either the running thread and/or the socket to get it to stop blocking
You should set the thread as daemon thread before it is started, using setDaemon(true). This will allow the JVM to terminate the thread automatically...
isRunning should be marked volatile or you should use AtomicBoolean instead
Related
I need to create a daemon in Java which periodically retrieves data via HTTP and stores that in a database.
When the main thread starts up, it reads the data sources and poll intervals from a configuration file and creates a TimerTask with the appropriate interval for each data source. In addition, it calls Runtime.getRuntime().addShutdownHook() to add a shutdown hook which performs any cleanup needed before shutdown. After that, the main thread has nothing else to do.
The daemon is intended for use in a classic Unix environment, i.e. controlled with a start/stop script, though it should be portable to other OSes (say, Windows with SrvAny).
How would I go about this? If I just let the main thread exit, will the TimerTask instances keep the VM running until all of them have been cancelled? If not, how would I accomplish this?
Threads in Java have a flag to indicate if they should keep the jvm alive or not. This flag is called "daemon": the jvm will exit when only daemon threads are running.
The thread started by Timer is not a daemon thread by default, so it will keep the jvm alive, which is what you want. If you wanted the jvm to exit, you could create the timer with new Timer(true) - this would set the daemon flag. https://docs.oracle.com/javase/10/docs/api/java/util/Timer.html#%3Cinit%3E(boolean)
It depends on the Timer on which the TimerTask was scheduled: if that Timer was created not to run its tasks as daemons, a pending TimerTask will keep the VM alive even after the main thread has finished its work. This is the case for all Timer constructors which do not take a boolean argument, or where the boolean argument is false.
The following seems to work as intended:
package com.example.daemon;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class SampleDaemon {
private static Timer testTimer = new Timer(false);
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Received shutdown request!");
if (testTimer != null)
testTimer.cancel();
testTimer = null;
}
});
testTimer.schedule(new TestTimerTask(), new Date(), 2000);
}
private static class TestTimerTask extends TimerTask {
#Override
public void run() {
System.out.println("Still running…");
}
}
}
It prints Still running… every 2 seconds. When the JVM receives a SIGTERM, the program prints Received shutdown request! and exits. This can also be accomplished by sending Ctrl+C from the console. SIGHUP does the same as SIGTERM.
SIGCONT has no effect; SIGUSR1 results in a hard exit (presumably the same as SIGKILL), i.e. without executing the shutdown hook.
Suppose a Java thread performs some I/O operation like reading a file with traditional blocking Java I/O.
The question is: What is the state of the thread while waiting?
I don't know if it is RUNNING (doing some active wait) or WAITING (maybe there is some kind of monitor that wakes up the thread when file data is ready).
How can I find it out?
Thanks.
A thread that is blocked in an I/O syscall should be in RUNNABLE state, according to my reading of the javadocs.
public static final Thread.State RUNNABLE
Thread state for a runnable thread. A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.
The other possible thread states are far more tightly specified, and the respective specifications make them clearly inapplicable.
I have confirmed this by testing (with OpenJDK Java 8 on Linux).
public class Test {
public static void main(String[] args) throws Exception {
Thread t = new Thread(new Runnable() {
public void run() {
try {
while (true) {
System.in.read(); // Block for input
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
while (true) {
System.out.println("State: " + t.getState());
Thread.sleep(1000);
}
}
}
Now, hypothetically, if you designed your application so that one thread handed off I/O requests to second thread, then the first thread would be in WAITING (or possibly BLOCKED) state waiting for the I/O thread to deliver. However, normal Java I/O doesn't behave like that. The thread requesting I/O is the one that makes the syscall.
How can I find it out?
Write tests; see above.
Deep-dive the OpenJDK source code.
You can find the status of thread using Thread.getState(). It will return
java.lang.Thread.State
I am writing a simple client/server chat program. The server handles multiple clients in this way:
public void start(int port)
{
(new Thread(new Runnable()
{
#Override
public void run() {
try{
serverSocket = new ServerSocket(port);
SocketHandler handler;
while(true)
{
handler = new SocketHandler(serverSocket.accept());
handlersList.add(handler);
(new Thread(new SocketHandler(socket))).start();
}
}catch(IOException e)
{
for(SocketHandler handler:handlersList)
handler.close();
}
}
})).start();
}
public void stop() throws IOException
{
serverSocket.close();
}
Basically start() instantiates the ServerSocket and waits for clients to connect indefinitely. Whenever the user wants to close the server, the Server Socket is closed, which causes the accept() to fail and to throw and exception. Then the catch(){} closes the various sockets created. My questions are:
Do I have to close every socket created through serverSocket.accept()?
Is this the right way to stop such a server? That while(true) + use of exceptions for non-exceptional circumstances feels so wrong to me. Is there a better way?
Could I use an ExecutorService and then just call shutdownNow on it? Will the shutdownNow be able to stop the accept() call? Because the api doc states that it is not guaranteed to succeed.
Please, feel free to point out any error/poor design choice that I've made. Ty
You can either close you connections manually (both client/server side) using the close() method or you can set a timeout.
Set a timeout on blocking Socket operations:
ServerSocket.accept();
SocketInputStream.read();
DatagramSocket.receive();
The option must be set prior to entering a blocking operation to take
effect. If the timeout expires and the operation would continue to
block, java.io.InterruptedIOException is raised. The Socket is not
closed in this case.
Is this the right way to stop such a server?
As you say it is a server that means you should not need to stop it but in exceptional conditions.
As you state the shutdownNow() API says:
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks.
I have the problem, that the join Method, to kill a thread, is not executing the rest of the method, which was started also in the thread. Here is a code example:
private static Thread thread;
public static void addMessage(final String s) {
thread = new Thread() {
#Override
public void run() {
String data = Message.send(s);
addMessageToContainer(data);
}
};
thread.start();
}
public static void addMessageToContainer(String data) {
//Do some stuff with the data
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//This code here will not be executed.
}
So normally, of course I can execute the code before I call the join function. But I have to load after this thread execution a webview with some content. So when I do remove the join, it will give me the following error message:
java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'Thread-9072'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {5ac9b39} called on null, FYI main Looper is Looper (main, tid 1) {5ac9b39})
So what can I do to load the content after the thread has executed?
Join doesn't kill a thread. Join waits until that thread kills itself. So that code would be executed- just at some time in the future, when that thread decides its done. Calling wait on a thread from that thread will cause it to deadlock and never do anything, yet never die. So in the case above where you're calling it from the thread itself, it will just hang forever.
There is no way to kill a thread directly, because its impossible to do so safely. The way to kill a thread from the outside is to interrupt it, and let the thread check if it isInterrupted() every so often and if so kill itself. The way to kill a thread from the inside is to return from the runnable's run method.
Your webview error is totally unrelated. You can only touch views on the main thread. Don't do anything with a webview on a thread.
I have code that schedules one-time tasks to execute and does this over and over. It looks something like this.
public static void main(String[] args)
{
while(true)
{
....
TimerTask closeTask = new CloseTask(cli);
Timer timer = new Timer(true);
timer.schedule(closeTask, (long) (iPeriod * 60 * 1000));
...
}
}
public class CloseTask extends TimerTask
{
Client client;
CloseTask(Client in_client)
{
client = in_client;
}
public void run()
{
try
{
for(int iRetries = 0; state == OPEN; iRetries++)
{
logger.log_trade_line_grablock( "Thread " + Thread.currentThread().getId() + ": About to send message", true, true, true, true, true);
client.send_mesg("close");
logger.log_trade_line_grablock( "Waiting 5 seconds before retrying ", true, true, true, true, true);
Thread.sleep(5000);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
The intent of the run() method in the CloseTask class is to loop until the state variable changes from OPEN state to something else. However, intermittently the timer threads simply disappear, while state still equals OPEN, which I know by printing out all the thread ID's of the currently running threads every 5 minutes.
So my questions:
1) The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. Is that correct?
2) If 1) is correct why isn't my try catch block catching these exceptions?
3) If 1) is correct is there a way to catch these exception that slip through uncaught?
Thanks for any insight into this issue.
You're creating a Timer instance, but not making sure that it doesn't get garbage collected.
From the documentation:
After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection).
So basically, you need to hold on to the reference to the Timer you created instead of just using a local variable.
The boolean you are passing in tells whether or not the thread created will be daemon. If it is daemon, the thread will be stopped once all non-daemon threads are finished. Since the only non-daemon thread being run in your application is the main thread then it will immediately be stopped after the main method is completed.
As Jon Skeet mentioned there is some completion operations done if no live thread is referencing the Timer and the tasks complete, but if it's daemon and the main method completes, it may not exit gracefully. To continue the documentation
... However, this can take arbitrarily long to occur. By default, the task execution thread does not run as a daemon thread, so it is capable of keeping an application from terminating. If a caller wants to terminate a timer's task execution thread rapidly, the caller should invoke the timer's cancel method.
To answer your question
The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. Is that correct?
If the JVM kills a non-daemon thread, it won't throw any exception. So you won't really know that it happened.