I'm about to learn the java threading facility.
I have 2 classes:
public class Main {
public static void main(String[] arg) throws Exception {
Timer timer = new Timer();
timer.schedule(new ExecuteTimer(Thread.currentThread()), 2000);
try {
Thread.currentThread().join();
} catch (InterruptedException ex) {
System.out.println("timer stopped");
}
System.out.println("try block executed");
}
}
and the timer class:
public class ExecuteTimer extends TimerTask {
public ExecuteTimer(Thread thread) {
creatingThread = thread;
}
private Thread creatingThread;
#Override
public void run() {
System.out.println("I'm executed!");
creatingThread.interrupt();
}
}
When I debug the code. I have following output:
I'm executed!
timer stopped
try block executed
Everything seems to be final except the app didn't exit after I have the output above. The eclipse remain in debug mode and no exception has been thrown.
After you no longer need the Timer to run tasks, you should call timer.cancel() to release its thread.
Use thread.setDaemon(true) to tell the JVM to make the thread a daemon thread. Daemon threads do not prevent the program from exiting.
Related
I have a simple test program (garage simulation) with several threads (Vehicle, MysteryVehicle, Observer objects) instantiated and started. Only the Observer object is a daemon thread running an infinite loop.
After all non-daemon threads terminate, Observer thread never does and the loop is executed infinitely (so this isn't some buffered output after the daemon thread really terminates - it does go on forever).
All of the non-daemon threads print something to the console just before exiting their run() methods, and it clearly shows all of them really terminated. I also didn't call join() on the daemon thread. When printing out all currently running threads, observer is listed as well, so my guess is that this daemon thread isn't terminating properly.
The complete code can be found on this commit.
Below you can see all threads created, started and where exactly is join() called.
Main.java
package garage;
import java.util.Set;
import garage.model.*;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Platform platform = new Platform();
Vehicle.platform = platform;
platform.print();
Vehicle[] vehicles = new Vehicle[30];
for (int i = 0; i < 30; i++) {
vehicles[i] = new Vehicle();
}
for (int i = 0; i < 30; i++) {
vehicles[i].start();
}
Observer observer = new Observer();
observer.platform = platform;
observer.start();
MysteryVehicle mysteryVehicle = new MysteryVehicle();
mysteryVehicle.start();
try {
mysteryVehicle.join();
} catch (Exception exception) {
exception.printStackTrace();
}
try {
for (int i = 0; i < 30; i++)
vehicles[i].join();
} catch (Exception exception) {
exception.printStackTrace();
}
System.out.println("before");
platform.print();
System.out.println("after");
synchronized (Platform.lock) {
System.out.println("END");
System.out.println(platform.flag); // checks whether wait() was called anytime
}
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread t : threads) {
System.out.println(t.getName());
}
}
public static void main(String[] args) {
launch(args);
}
}
Observer.java
package garage.model;
public class Observer extends Thread {
public Platform platform;
static int count = 0;
{
setName("observer");
setPriority(MIN_PRIORITY);
setDaemon(true);
}
#Override
public void run() {
while (true) {
synchronized (Platform.lock) {
try {
System.out.println(++count);
platform.print();
Platform.lock.wait(5000); // hack for when there is no meaningful loop condition
} catch (InterruptedException exception) {
exception.printStackTrace();
} finally {
Platform.lock.notifyAll();
}
}
}
}
}
Vehicle run() method - relevant part
public void run() {
...
System.out.println("done");
}
MysteryVehicle run() method - relevant part
public void run() {
synchronized (Platform.lock) {
System.out.println("And the vehicle disappears!");
...
}
}
All of the relevant thread messages are printed out to the console.
done - 30 times, And the vehicle disappears!, before, after, END, true
This is the list of all of the running threads:
Attach Listener
main
Common-Cleaner
JavaFX Application Thread
Signal Dispatcher
Finalizer
InvokeLaterDispatcher
Reference Handler
QuantumRenderer-0
observer
Thread-2
JavaFX-Launcher
Since the program doesn't terminate and the print() function the run() method of observer calls is executed infinitely, what is it that prevents the daemon thread from terminating?
What am I missing here?
I suspect main() never returns, so the main thread (and perhaps some of those FX threads) are still running.
From the Application doc:
The launch method does not return until the application has exited,
either via a call to Platform.exit or all of the application windows
have been closed.
The posted code has no window to close nor is Platform.exit() invoked.
As far as I know, calling join on daemon thread is a bad idea.The idea behind using daemon thread is it will not halt JVM from exiting. What you can do is send an interrupt to that thread and call join after that.
I am trying to set up a shutdown hook to handle SIGTERM (kill -15). It shuts down but doesn't look like it gracefully finish up ** processing** function as it never output the log "Thread has been shutdown".
public class Runner {
public static void main(String[] args) {
Test test = new Test();
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
logger.warn("Shutting things down..."); // This works
test.stop();
} catch (Exception ex) {
logger.error("Error shutting the app gracefully", ex);
}
}
});
test.processing();
}
}
public class Test {
private volatile boolean processingExit = false;
public void stop() {
processingExit = true;
}
public void processing() {
while (!processingExit) {
//do work here
logger.info("doing work... keep printing..."); //This works until I send a kill -15 signal
}
// This log never works
logger.info("Thread has been shutdown"); // This doesn't works
}
}
The problem is that as soon as the shutdown hook thread completes, the process is halted, you need to have the shutdown hook thread wait for the main thread.
Copied from https://stackoverflow.com/a/2922031/1544715
From the docs:
When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt.
I have a thread which runs a task of file parsing. Its set as a daemon thread which runs in background from tomcat startup to shutdown doing its task.
I am looking to handle thread termination upon interruption and server shutdown. I want to know if am going about correctly.
class LoadingModule{ // Thread is started from here
threadsStartMethod() {
Thread t = new Thread(FileParseTask);
t.setDaemon(true);
t.start();
}
}
Class FileParseTask implements Runnable {
#Override
public void run() {
try {
while(!Thread.currentThread.isInterrupted) {
// poll for file creation
// parse and store
}
} catch(Exception exit) {
log.error(message);
Thread.currentThread.interrupt();
}
}
}
would this cleanly exit the thread in all scenarios?
it would depend on the code inside the loop. If the code inside the loop captures the interrupted exception and recovers, you will never see it. Also generic exception "exit" hides other exceptions. Change the code so you know what hit you.
I would do the following
Class FileParseTask implements Runnable {
#Override
public void run() {
while(!Thread.currentThread.isInterrupted) {
try {
// poll for file creation
// parse and store
} catch(Exception exit) {
if (InterruptedException)
break;
else{
//
}
log.error(message);
}
}
}
}
This has worked for me with up to 2K threads with no problems
I have a client-server application that runs the receive method to run in a separate thread. Thread is given some time to finish the job and the thread will be checked for the status.
There are occasions when the receive method will be blocked due to packet or ACK loss. If that happens, how can I stop the thread and start it again the next attempt?
As we all know, Thread.stop() is deprecated.
You can't restart a Java thread at all, with or without Thread.stop().
You have to create a new one.
You can however reuse a Runnable.
You can use interrupts to send to the thread and handle them to do a retry. Here is a sample that will start a thread that will not quit until the boolean done is set. However i'm interrupting the thread from a main thread to make it start over.
public class Runner implements Runnable {
private boolean done;
#Override
public void run() {
while (!done) {
try {
doSomeLongRunningStuff();
} catch (InterruptedException e) {
System.out.println("Interrupted..");
}
}
}
private void doSomeLongRunningStuff() throws InterruptedException {
System.out.println("Starting ... ");
Thread.sleep(300);
System.out.println("Still going ... ");
Thread.sleep(300);
done = true;
System.out.println("Done");
}
public static void main(final String[] args) throws InterruptedException {
final Thread t = new Thread(new Runner());
t.start();
Thread.sleep(500);
t.interrupt();
Thread.sleep(500);
t.interrupt();
}
}
Whether you can do it this way or not depends on what you are calling. Your framework doing the TCP connection may or may not support interrupting.
We should not restart a thread which is not valid , once thread has comepleted its execution.
In C programs using system threads for example, I can pass a SIGINT with Ctrl+C and the process will be killed silently. But when I do the same thing to a Java program with threads, locks, semaphores et cetera, the JVM just stops there and I have to kill the process "outside", by closing the terminal or rebooting the system. How can a make a Java program silently exit as it should without closing the terminal when I see some wrong behaviors in runtime?
You can add a shutdown hook to the JVM that gets triggered when a SIGINT is received and then in there call Runtime.getRuntime().halt(0). That will kill the process. You can even use the Shutdown Hook to clean your running Threads.
[EDIT] My initial answer was to use System.exit() in the hook. But that will not work because System.exit will trigger the already running hook.
You can try this example with the hook and not registering the hook.
public class Exit {
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new ExitHok());
Thread t = new Thread(new Printer());
t.start();
}
private static class ExitHok extends Thread {
#Override
public void run() {
System.out.println("Received shutdown");
Runtime.getRuntime().halt(0);
}
}
private static class Printer implements Runnable {
#Override
public void run() {
int counter = 0;
while (true) {
System.out.println(++counter);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
}