Non-blocking thread that runs an external process - java

I have created a Java GUI application which functions as a wrapper for many low level external processes. The utility works as is, but is in desperate need of one major improvement.
I want my external process run in a non-blocking manner which would permit me to service additional requests in parallel. In a nutshell I want to be able to process data from the external process as the data is being generated. But it appears my basic attempt to check and see if the external process is still running is blocking.
Below is an excerpt from my ExternalProcess class. Please see inline comments for specific Java functionality questions about threading and blocking.
public void Execute()
{
System.out.println("Starting thread ...\n");
Runner = new Thread(this, "ExternalProcessTest");
Runner.run();
System.out.println("Ending thread ...\n");
}
public void run()
{
System.out.println("In run method ...\n"); // Debug purposes only.
// Show that we are in the run loop.
try
{
// Execute string command SomeCommand as background process ...
Process = Runtime.getRuntime().exec(SomeCommand);
while(IsRunning())
{
// External process generates file IO. I want to process these
// files inside this loop. For the purpose of this demo I have
// removed all file processing to eliminate it as the cause
// of blocking. THIS ROUTINE STILL BLOCKS!
Thread.sleep(1000);
}
}
catch(Exception e)
{
System.out.println(e);
}
System.out.println("Exiting run method ...\n"); // Debug purposes only.
// Show that we are exiting the run loop.
}
// Process (instantiated from Runtime.getRuntime().execute doesn't supports
// either fire-and-forget backgrounding (non-blocking) or you can wait for
// the process to finish using the waitFor() method (blocking). I want to
// be able to execute a non-blocking external process that I monitor via
// threading allowing me to process the external process file IO as it is
// created. To facilitate this goal, I have created an isRunning() method
// that uses the exitValue() method. If the process is still running, a
// call to exitValue() will throw an IllegalThreadStateException exception.
// So I simply catch this execption to test if the background process is
// finished -- at which point I can stop processing file IO from the
// process. Is this the source of the blocking? If so, is there another
// way to do this?
public boolean IsRunning()
{
boolean isRunning = false;
try
{
int exitVal = Process.exitValue();
}
catch(IllegalThreadStateException e)
{
isRunning = true;
}
return isRunning;
}

The run() method on Thread doesn't actually start a new thread, try using Thread.start() instead.

Runner = new Thread(this, "ExternalProcessTest");
Runner.run();
The run() method is deceptively named. Because Thread implements the Runnable interface the run() method is exposed publicly, but it is not the right method to call when you want to kick off a new thread. Calling run() causes the thread code to be run in the current thread.
You must call start() to cause a new thread to be instantiated:
Runner = new Thread(this, "ExternalProcessTest");
Runner.start();

Related

Interrupting a normally running thread in java

I am trying to interrupt a normally running thread (which is not in sleep() or wait() state) .
while going through in net i got to know interrupting a normally running thread will just set the flag true and continue the process.
Code snippet is
one.java
......
......
actionperformedmethod {
if (actionCmd.equals("cancel")) {
try {
r1.stop(); // to two.java
} catch (InterruptedException ex) {
....
....
}
}
}
in two.java
.....
.....
stop method() throws InterruptedException{
if(!(t.isInterrupted())){
t.interrupt();
throw new InterruptedException();
}
}
from two.java when i throw InterruptedException i can able to get the exception block at one.java , but how do i stop the thread after that because even after that thread seems to continue the normal process.
Am new to thread concepts please help..
The interrupt() method is co-operative rather than pre-emptive - the background task needs to actively check Thread.interrupted() at suitable intervals, and take action to shut itself down cleanly.
public void run() {
openSomeResources();
try {
while(notFinished) {
if(Thread.interrupted()) return;
doSomeStuff();
}
} finally {
closeTheResources();
}
}
In this example if the thread is interrupted in the middle of doSomeStuff() then it will complete the current "iteration" before responding to the interruption. Getting the correct balance between responding promptly to an interrupt on the one hand, and responding only at a safe point in the execution on the other hand, is something that is inherently specific to the particular task - there is no one-size-fits-all answer.
Note however that any blocking method that throws an InterruptedException will reset the interrupt flag when this exception is thrown. Therefore in order for this sort of checking to work you must re-interrupt yourself whenever you receive an InterruptedException
try {
Thread.sleep(3000);
} catch(InterruptedException e) {
// we were interrupted - set the flag so the next interrupted() check will
// work correctly.
Thread.currentThread().interrupt();
}
Interrupt will not stop the thread. it just sets the flag to true to signal the thread to stop the execution soon.
to stop the execution
add global variable as
private volatile boolean exit = false;
and
you add one method in your 2nd class
public void requestExit(){
exit = true;
}
inside run () of your thread do something like this
if (exit == true){
return;
}
whenever you want to call just call this method requestExit() from your main() or wherever you want to stop
this is the best way to stop the thread.. using stop() on thread is dangerous as it does not clear any resources and its not advisable to use even by oracle hence deprecated.
let me know for any issues
Threads are only running whilst their run() method is on the stack so usually people put a while(true) inside the run method, all you need to do in you thread to stop it is to return somewhere in the run method or break the loop then as soon as the run() method is no longer running the thread has been stopped.

Queries regarding Shutdown hook

If i have gotten it correctly each java process is associated with a separate instance of JVM and each instance of JVM is provided with a Heap memory by the OS which is also recollected by the OS on JVM termination. So on termination even if there were some memory leaks all the memory will be reclaimed by the OS(Please correct if I have mistaken).
In case point number 1 is true why do we have to use shutdown hooks. After googling everything mainly suggests to free all the resources and graceful shutdown. Even if it does not gracefully shutdown all the memory and resources would be freed?
I wrote a simple shutdown hook. In my main thread I am running an infinite loop and then terminating the process using terminate button in Eclipse. But the shutdown hook thread is not running.
Does terminating process in eclipse call Runtime.getRuntime().halt(status) because AFAIK that terminated JVM abruptly and not execute shutdown hook?
Lastly if I have my main code something like below -
public static void main(String args[]){
Runtime.getRuntime().addShutdownHook(new Thread(new ShutDownHook()));
System.out.println("Shutdown hook registered");
System.out.println("Before calling exit");
System.exit(0);
System.out.println("After exit");
}
why is After exit not printed? When shutdown hook is in execution main thread must continue further execution and print After exit?
1) You are correct.
2) The Java process' memory will be reclaimed, but you might want to do other cleanup, like delete some temp files.
3) Let's go to the javadoc of Runtime#addShutdownHook(Thread)
The Java virtual machine shuts down in response to two kinds of
events:
The program exits normally, when the last non-daemon thread exits or
when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt,
such as typing ^C, or a system-wide event, such as user logoff or
system shutdown.
You would have to look into Eclipse's source code, but it would seem like Eclipse terminates the process rather than sending a System.exit(..) or a sending a user interrupt. This probably goes over the JVM which therefore doesn't execute the shutdown hooks.
4) The shutdown hooks you add with Runtime#addShutdownHook(Thread) are added to a static IdentityHashMap in the ApplicationShutdownHooks. This class registers its own shutdown hook with the Shutdown class in a static initializer block shown below
static {
try {
Shutdown.add(1 /* shutdown hook invocation order */,
false /* not registered if shutdown in progress */,
new Runnable() {
public void run() {
runHooks();
}
}
);
hooks = new IdentityHashMap<>();
} catch (IllegalStateException e) {
// application shutdown hooks cannot be added if
// shutdown is in progress.
hooks = null;
}
}
The runHooks() method is
static void runHooks() {
Collection<Thread> threads;
synchronized(ApplicationShutdownHooks.class) {
threads = hooks.keySet();
hooks = null;
}
for (Thread hook : threads) {
hook.start();
}
for (Thread hook : threads) {
try {
hook.join();
} catch (InterruptedException x) { }
}
}
So the current thread joins all the other ones.
When
System.exit(0);
gets called, somewhere down the line Shutdown.sequence() gets called which invokes Shutdown.hooks() implemented as
private static void runHooks() {
for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
try {
Runnable hook;
synchronized (lock) {
// acquire the lock to make sure the hook registered during
// shutdown is visible here.
currentRunningHook = i;
hook = hooks[i];
}
if (hook != null) hook.run();
} catch(Throwable t) {
if (t instanceof ThreadDeath) {
ThreadDeath td = (ThreadDeath)t;
throw td;
}
}
}
}
One of the Runnable objects in hooks is what I described above. It doesn't spawn a new Thread, it does it concurrently with run().
Once Shutdown.sequence() is done, the system really exits, so the final System.out.println() doesn't execute.

Java thread doesn't stop/interrupt

I'm trying to terminate a thread but it doesn't interrupt or stop. All of this are part of controller of a software called Webots. I use this to simulate a multi robot system. In the controller of each robot, I start a thread which receive messages through robots receivers. This thread must start at first, and terminate when simulation ends.
The run method for this thread look like this:
public void run() {
while (true)
{
String M = recieveMessage();
char[] chars = M.toCharArray();
if(chars[0]==robotName||chars[0]=='0')
messages.add(M);
}
}
In the main controller I have code that look like this:
MessageThread MT = new MessageThread(messages, receiver,getName());
MT.start();
for (int i = 0; i < 100; i++)
{
try
{
Thread.sleep(25); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(messages.get(messages.size()-1));
}
MT.interrupt();//MT = null;
System.out.println(MT.interrupted());
It's not important what I do in my main controller, so don't judge it. For example, messages is an ArrayList. It's like a buffer which MT put messages in and the main thread reads from. I use it because the receiver and emitter are not synchronized.
If I call interrupt() or MT = null but interrupted() it returns false and MT continues to run. Is there anything wrong in my code?
I read some topics like:
http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
How do you kill a Thread in Java?
interrupt() doesn't work
Java: How interrupt/stop a thread?
and so on but I couldn't find any useful answer.
Edit
Thanks everyone, I've made changes to my code. I added this to the MessageThread class:
private volatile boolean isRunning = true;
Then I used while(isRunning) instead of while(true) and I added
public void kill()
{
isRunning = false;
}
and called MT.kill() instead of MT.interrupt().
It worked but I couldn't find out what's wrong with interrupt(). I read the link which #ExtremeCoders recommended. However, I'm still confused. It says "a thread must support its own interruption". So do I have to overwrite the interrupt() method? I can't call interrupt to terminate a thread?
Thanks again.
Interrupting a thread just sets a flag on the thread. If the thread never checks the flag, it won't respond. By creating your own boolean member, you've duplicated that functionality unnecessarily.
Here's the general pattern for what you are trying to do:
#Override
public void run() {
while(!Thread.interrupted() {
/* Do something. */
}
Thread.currentThread().interrupt();
}
This will allow you to call MT.interrupt() as you expected. It's better than creating your own flag and custom method to set it: you can use your Runnable task with high-level tools like ExecutorService and cancellation will work because you used the standard API; same is true for interruption of an entire ThreadGroup.
Calling Thread.interrupted() clears the interruption status of a thread; we set it by calling Thread.currentThread().interrupt(), the status is set again so that callers of run() can detect the interrupted state. This might not always be desirable however.

How to stop threads used for watching folders by using WatchService? [duplicate]

This question already has answers here:
How to stop threads of following type in Java used for watching folders for files using WatchService for folders by using jToggleButton
(4 answers)
Closed 9 years ago.
I would like to stop threads generated in the following manner. The threads are used for watching folders for files. I tried a lot, and searched a lot, but am not successful.
Could any body help and suggest any solution to stop threads generated like the following:
public class HelloRunnable implements Runnable {
public void run() {
WatchService for files in folders which starts and runs here
while (someCondition) {
create a thread for copying some file which exits when run() finishes
created in another class which implements Runnable class
}
}
public static void main(String args[]) {
for(int i = 0;i< 5; i ++)
new Thread(new HelloRunnable()).start();
}
}
You can use a boolean someCondition variable which is shared between the running thread and thread that wants to stop it. This variable needs to be volatile however to make sure that it's value is updated between the threads.
Another idea is to test the thread interrupt flag:
// thread that is spinning doing some job like watching a file
while (!Thread.currentThread().isInterrupted()) {
...
}
Then you can call interrupt from another thread to stop it from running:
Thread thread = new Thread(...);
thread.start();
...
// tell the thread running in the background to stop
thread.interrupt();
Like always, you need to be careful about catching InterruptedException. Something like the following is always a good idea:
try {
...
} catch (InterruptedException ie) {
// re-interrupt the thread now that we've caught InterruptedException
Thread.currentThread().interrupt();
// probably quit the thread
return;
}
if you want to stop a thread - its run() method must complete and exit. So check your condition in the run() method to ensure it eventually completes and exits.

Check execute code when thread is finished

I didn't fully understand the concept of threads I have some questions. Assume we have the following code:
ExecCommand.java
// I don't know how this work, for now
package therads;
// Here we will have the methods and run them from the Main.java
public class ExecCommand implements Runnable
{
String name;
int time;
public ExecCommand(String s,int amount)
{
name = s;
time = amount;
}
// Run method (Runnable)
public void run()
{
try
{
// What to execute when the thread is started
System.out.printf("%s is sleeping for %d\n",name,time);
Thread.sleep(time);
System.out.printf("%s is done\n",name);
}
catch(Exception e)
{
}
}
// This dosen't work when the thread is stopped
public void stop()
{
try
{
System.out.printf("STOPPED!");
}
catch(Exception e)
{
}
}
// This dosen't work when the thread is started
public void start()
{
try
{
System.out.printf("Started!");
}
catch(Exception e)
{
}
}
}
and i call him from :
Main.java
Thread t5 = new Thread(new ExecCommand("Good Function",1000));
t5.start();
I want to println() "Started" when the thread is started and "Stopped" when it finished. It is possible?
When a thread is completed, it dies, complete released from memory? If not, how i can do that?
How can i make a thread that repeat itself like once every 1000 miliseconds till i press a key? I was thinking about while(true) { t5.start; }
but i don't know for sure.
First of all, there is no point in using the start and stop methods. Everything happens in the run method.
To print a message on start and stop, put them at the start and end of the run method. To loop indefinitely and keep executing code until an outside event happens, use a flag and loop on it:
class ThreadTask implements Runnable {
private volatile boolean flag = false;
public void setFlag(boolean value) {
flag = value;
}
public void run() {
System.out.println("Started");
while(!flag) {
// execute code
}
System.out.println("Stopped");
}
}
Then when you want the thread to stop, just set the flag to true using setFlag.
And yes, threads are automatically cleaned up by the runtime + OS after the run method terminates.
Why or when would you expect your .start() and .stop() to be called? Runnable has only a single method in the interface; .run(). The JavaDocs for Thread cover it pretty well. http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html. If you want something to happen when your Thread starts, put that something at the top of your .run(). If you want something to happen when your Thread is finishing, put it at the bottom of the .run(). By-in-large doing anything with the .start() and .stop() methods on Thread is discouraged. Concentrate on doing all you lifecycle stuff within your .run(). And get a copy of "Java Concurrency in Practice" by Goetz. It will show you the full range of your options (including don't do you own Threading directly).
You are not supposed to override the start and stop methods. They are not callback methods.
What you want is something akin to the SwingWorker class (assuming you are interested in UI related threading synchronization).
If not, you can subclass Thread yourself and provide a callback mechanism.
Yes of course. You can just print "Started" in the first line of your run() method, and print "Stopped" either in a finally section of run() method or just after t5.join()
You are not told about the details, and cannot do anything. But you can assume the resources are freed as soon as necessary. (Of course if you have reachable links for any references allocated within your thread, JVM cannot decide that these are of no use, so "complete" is not a proper word here.)
Take a look at java.util.Timer
If you prefer to use System.out.println instead of printf just change those lines of code. There's nothing thread-related about those calls.
The thread will be collected and released from memory by the garbage collector when it has stopped running and there are no live references to it. Same as all objects.
Don't override stop(). This has been deprecated and should really be dealt with by the JVM, not your application code. Just override run to implement whatever you want your thread to do, as per the docs
You can use Thread.sleep to sleep for a period of time. How accurate the sleep will be will depend on your platform and the resolution of the available system clock.

Categories