How long does the JVM wait for a thread - java

Hi Every JAVA Developper,
I have juste a simple Question about JVM, i want to know how long the JVM will wait for a thread ?
For Example, take a look at this code :
public static void main(String[] args) {
p = Runtime.getRuntime().exec("myShellCommand -p1 v1 -p2 v2");
p.waitFor();
System.out.println("End ....:)");
}
Suppose that "myShellCommand" running for ever, whats happen then ? the JVM still also waiting for ever ?

the waitFor method causes the current thread to wait, if necessary, until the process represented by this Process object has terminated. This method returns immediately if the subprocess has already terminated. If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.(From the Javadoc).
Based on the documentation, I think that it will run forever.

In your case, the JVM would continue to wait for the launched process to terminate.
However, you could launch another "process monitor" thread and that could wait/sleep for a reasonable time and then interrupt the main thread.
As per the javadoc of the waitFor method
if the current thread is interrupted by another thread while it is
waiting, then the wait is ended and an InterruptedException is thrown.

#Kaoutar
If your requirement is to launch the process and then exit the JVM after a reasonable time period, e.g. 10 minutes, then you could do something like this:
public static void main(String[] args)
{
Thread subProcessThread = new Thread(new Runnable()
{
#Override
public void run()
{
Process p;
try
{
p = Runtime.getRuntime().exec("myShellCommand -p1 v1 -p2 v2");
p.waitFor();
System.out.println("End ....:)");
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
});
subProcessThread.start();
long waitTimeInMillis = 10 * 60 * 1000;
subProcessThread.join(waitTimeInMillis);
}

Related

How to interrupt or kill a java thread while it's running

After reading several SO posts on how to kill a Java thread, I fairly understand why stop is unsafe and how to handle the graceful stop.
But the solutions are targeting towards UI threads where repainting is the problem and not really a long running - blocking process executed by a thread.
Links:
How do you kill a Thread in Java?
https://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
One precise point that I fail to understand from the solutions or examples is what is the long-running-part the samples are trying to simulate.
Eg: In this following code, what if I set the interval to INT.MAX.
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval); // This might take forever to complete,
// and while may never be executed 2nd time.
synchronized(this) {
while (threadSuspended && blinker==thisThread)
wait();
}
} catch (InterruptedException e){
}
repaint();
}
}
public synchronized void stop() {
blinker = null;
notify();
}
The reason am asking for this use case is that, I have a bug in a legacy code base that runs another executable in a Thread.
Now the ask if the user wishes to stop the thread, we would need to kill this thread, and the executable which is part of this thread automatically gets killed.
The way you stop a thread is by asking it - nicely - to stop. It's up to the code the thread is running to listen for and act on that request.
Specifically, the way you do it is to interrupt the thread. Your code checks for the interruption - Thread.sleep and Object.wait will throw InterruptedException if the thread is interrupted before or during their execution; but you catch the interruption, and ignore it, so you won't act on it.
Instead of this:
while (condition) {
try {
Thread.sleep(...);
wait();
} catch (InterruptedException e) {
}
}
Put the interruption outside the loop:
try {
while (condition) {
Thread.sleep(...);
wait();
}
} catch (InterruptedException e) {
}
then the loop terminates if it is interrupted.

Move to main thread after another thread go to sleep

I have my main and a thread running alongside it, I want to be able to run the thread first and then move to any other thread, for example, my main.
I tried to look over google but could not find an answer.
public class AutoUpdater implements Runnable {
public void run() {
System.out.println("Thread is running...");
for (int i = 0; i < clients.size(); i++) {
do something...
}
System.out.println("Thread ended.\n");
int time = 1000 * 60 * 60 * 24;
try {
Thread.sleep(time);
} catch (InterruptedException e) {
System.out.println("Something interrputed thread while running.");
}
}
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Runnable runnable = new AutoUpdater(clients);
Thread thread = new Thread(runnable);
thread.start();
// run after the above thread finish and go to sleep
System.out.println("This is a test");
}
Like I said above I want my thread to finish and go sleep for X time, for example, 24 hours and when it goes to sleep move back to my main thread.
The goal is to make a bank system that updates all clients accounts first and then the method run (my second Thread) will go sleep for the next 24 hours. and move back my main.
What you have done in your code above created a thread that runs concurrently with the main thread. What actually happens is:
Main thread starts and initiates AutoUpdater thread
The two threads will run concurrently. In fact, the Main thread may even terminate before the AutoUpdater thread has really started.
The auto-update thread processes the clients ONCE, then sleeps for 24 hours and then terminates and your program completely terminates at this point.
So sticking with what you have, the first step is to get the AutoUpdater thread to run every 24 hours. One way you could do this is to keep the thread running and put a while loop in the run method so that it doesn't terminate but processes the clients collection every 24 hours. So now AutoUpdater might look like this:
public class AutoUpdater implements Runnable {
public void run() {
while (true) {
try {
System.out.println("Thread is running...");
for (int i = 0; i < clients.size(); i++) {
// do something...
}
} finally {
System.out.println("Thread ended.\n");
}
int time = 1000 * 60 * 60 * 24;
try {
Thread.sleep(time);
} catch (InterruptedException e) {
System.out.println("Something interrputed thread while running.");
}
}
}
}
However, the code above has some issues in that it will drift. If for example, processing takes an hour then the next time it runs will be 25 hours after the last run initial started. Fortunately, Java provides a thread executor service that will run your thread on a fixed schedule called ScheduledExecutorService. So let's unwind the while loop and introduce the executor instead.
public class AutoUpdater implements Runnable {
public void run() {
System.out.println("Thread is running...");
for (int i = 0; i < clients.size(); i++) {
// do something...
}
System.out.println("Thread ended.\n");
}
}
public static class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(
new AutoUpdater(clients, lock.writeLock()),
0,
24,
TimeUnit.HOURS);
System.out.println("This is a test");
}
}
Now we've got the auto-updater thread running every 24 hours from when we started the process. If you want to fix the time, i.e. at 8 AM every day you can either calculate the delay till that time (though this won't take into account daylight saving issues) or use a third-party library like Quartz to schedule at a specific time of day.
I want to be able to run the thread first and then move to any other thread, for example, my main.
Presumably by this, you mean that you want to stop other threads from executing while the Auto-Update is running. For this, you have several options available. In the first instance, you can use a monitor to synchronize and lock threads, i.e.
Object sharedMonitor = new byte[0]
// In your auto-updater and other threads
synchronised(sharedMonitor ) {
}
The syntax above will only allow a single thread to enter a synchronized block at a time for the same monitor instance. This would work fine in the example above where you only have the two threads. If you have more than the two threads it becomes problematic as you only really want the other threads to block when the auto-updater is running. In this case, this isn't the right solution for you. What you are after is something that will let all the threads run concurrently until the auto-updater needs to run and then they all need to block and wait for the auto-updater to finish. Fortunately for you, Java has a ReadWriteLock which does exactly that.
So let's add that lock and use it.
public static class Main {
private static List<String> clients = new ArrayList<>();
public static void main(String[] args) throws IOException, ClassNotFoundException {
ReadWriteLock lock = new ReentrantReadWriteLock();
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(
new AutoUpdater(clients, lock.writeLock()),
0,
24,
TimeUnit.HOURS);
Lock readLock = lock.readLock();
while (true) {
try {
readLock.lock();
System.out.println("This is a test");
} finally {
readLock.unlock();
}
}
}
}
So above we have:
Added a read-write lock
Passed the write lock to AutoUpdater
Added a while loop to the main method so it doesn't terminate and can do whatever run-of-the-mill processing it is meant to be doing.
In the while loop we've acquired the read lock at the start and released it at the end.
The last piece of the puzzle is to use the write lock in AutoUpdater
public class AutoUpdater implements Runnable {
public void run() {
try {
lock.lock();
System.out.println("Thread is running...");
// do something...
}
} finally {
System.out.println("Thread ended.\n");
lock.unlock();
}
}
}

Thread-launched running processes won't destroy (Java)

Starting multiple threads and having each exec() then destroy() a running java process result in some of the process not being destroyed and still running after program exit. Here is some code that reproduce the issue. I noticed the more threads you start, the more processes stay alive. And the more sleep before destroy(), the less processes stay alive. (I used InfiniteLoop as an example. Any running process will do the trick.)
EDIT : Bug has been reported to Oracle, waiting for an answer. Feel free to share any knowledge/experiments on the subject.
for(int i = 0; i < 100; i++)
{
new Thread(new Runnable()
{
public void run()
{
try
{
Process p = Runtime.getRuntime().exec(new String[]{"java", "InfiniteLoop"});
Thread.sleep(1);
p.destroy();
}catch(IOException | InterruptedException e){e.printStackTrace();}
}
}).start();
}
Use a p.waitFor(); before p.destroy(); ,
this will ensure the completion of the previous process. I think you p.destroy command gets invoked sooner than the exec() command performs the action. Therefore it becomes useless.
If subprocesses write anything to stdout or stderr (intentionally or not), that could cause trouble:
"Because some native platforms only provide limited buffer size for
standard input and output streams, failure to promptly write the input
stream or read the output stream of the subprocess may cause the
subprocess to block, and even deadlock."
Source: http://www.javaworld.com/jw-12-2000/jw-1229-traps.html
The whole article is IMO worth reading if you need to use Runtime.exec().
This is simply because before the threads execute the destroy call, your main program terminates and all the associated threads leaving the started processes running. To verify this, simply add a System.out call after the destroy and you will find it is not executed. To overcome this add a Thread.sleep at the end of your main method and you will not have the orphaned processes. The below does not leave any process running.
public class ProcessTest {
public static final void main (String[] args) throws Exception {
for(int i = 0; i < 100; i++) {
new Thread(new Runnable()
{
public void run() {
try {
Process p = Runtime.getRuntime().exec(new String[]{"java", "InfiniteLoop"});
Thread.sleep(1);
p.destroy();
System.out.println("Destroyed");
}catch(IOException e) {
System.err.println("exception: " + e.getMessage());
} catch(InterruptedException e){
System.err.println("exception: " + e.getMessage());
}
}
}).start();
}
Thread.sleep(1000);
}
}
You should close the input/output/error streams to the process. We saw some issues in the past where the forked process was not completing properly due to those streams not being closed (even if they weren't being used).
An exemplary solution:
p.destroy();
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
I believe that according to link, a distinct process is spawned by the operating system in response to this call. This process has a lifetime independent of your Java program and threads within it so you would expect it to continue running after your program has exited. I just tried it on my machine and it appeared to work as expected:
import java.io.*;
class Mp {
public static void main(String []args) {
for(int i = 0; i < 100; i++) {
new Thread(new Runnable() {
public void run() {
try {
System.out.println("1");
Process p = Runtime.getRuntime().exec
(new String[]{"notepad", ""});
System.out.println("2");
Thread.sleep(5);
System.out.println("3");
p.destroy();
System.out.println("4");
}
catch(IOException | InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
This is not an answer; I am posting complete source for my own attempt at recreating this problem as per discussion in question comments.
I cannot reproduce this problem on Ubuntu 12.04; OpenJDK 6b_27 (however, see below).
ProcessTest.java:
import java.io.*;
public class ProcessTest {
public static final void main (String[] args) throws Exception {
for(int i = 0; i < 100; i++) {
new Thread(new Runnable()
{
public void run() {
try {
Process p = Runtime.getRuntime().exec(new String[]{"java", "InfiniteLoop"});
Thread.sleep(1);
p.destroy();
}catch(IOException e) {
System.err.println("exception: " + e.getMessage());
} catch(InterruptedException e){
System.err.println("exception: " + e.getMessage());
}
}
}).start();
}
}
}
InfiniteLoop.java
public class InfiniteLoop {
public static final void main (String[] args) {
while (true) ;
}
}
I cannot reproduce the issue where processes remaining running after the JVM terminates. However, if I add a long delay in the main thread after starting the threads but before returning from main, I do see roughly a dozen running java processes that stick around (although they are terminated when the main program terminates).
Update:
I just had it leave about 5 processes running after it terminated. It doesn't always happen. Weird. I want to know more about this too. I have a hunch that it has something to do with destroying the process too quickly or some kind of race condition; maybe java forks something off or does something to create a new process that destroy() doesn't take care of if called too quickly / at the wrong time.
I found an old bug (but it is not mark resolved) stating that if a process spawns subprocesses they may not be killed by destroy(). bugs.sun.com/bugdatabase/view_bug.do?bug_id=4770092 What version of the JDK are you using.
Here's another reference to what looks like a similar issue: Java tool/method to force-kill a child process And I want to apologize if I've only added confusion to your life, I don't actually use Process that much and am not familiar with the quirks. Hopefully somebody else will step in with a definitive answer. It seems like it doesn't handle subprocesses well, and I'm presuming java forks something off. That's all I got.
There is a race condition between the time Runtime.exec kicks off a new thread to start a Process and when you tell that process to destroy itself.
I'm on a linux machine so I will use the UNIXProcess.class file to illustrate.
Runtime.exec(...) will create a new ProcessBuilder and start it which on a unix machine creates a new UNIXProcess instance. In the constructor of UNIXProcess there is this block of code which actually executes the process in a background (forked) thread:
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
Thread t = new Thread("process reaper") {
public void run() {
try {
pid = forkAndExec(prog,
argBlock, argc,
envBlock, envc,
dir,
redirectErrorStream,
stdin_fd, stdout_fd, stderr_fd);
} catch (IOException e) {
gate.setException(e); /*remember to rethrow later*/
gate.exit();
return;
}
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
stdin_stream = new BufferedOutputStream(new
FileOutputStream(stdin_fd));
stdout_stream = new BufferedInputStream(new
FileInputStream(stdout_fd));
stderr_stream = new FileInputStream(stderr_fd);
return null;
}
});
gate.exit(); /* exit from constructor */
int res = waitForProcessExit(pid);
synchronized (UNIXProcess.this) {
hasExited = true;
exitcode = res;
UNIXProcess.this.notifyAll();
}
}
};
t.setDaemon(true);
t.start();
return null;
}
});
Notice that the background thread sets the field pid which is the UNIX process id. This will be used by destroy() to tell the OS which process to kill.
Because there is no way to make sure that this background thread has run when destroy() is called, we may try to kill the process before it has run OR we may try to kill the process before pid field has been set; pid is uninitialized and therefore is 0. So I think calling destroy too early will do the equivalent of a kill -9 0
There is even a comment in the UNIXProcess destroy() that alludes to this but only considers calling destroy after the process has already finished, not before it has started:
// There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check,
// there is an unavoidable race condition here, but the window
// is very small, and OSes try hard to not recycle pids too
// soon, so this is quite safe.
The pid field is not even marked as volatile so we may not even see the most recent value all the time.
I had a very similar issue and the problem with destroy() not working was manifesting even with a single thread.
Process process = processBuilder(ForeverRunningMain.class).start()
long endTime = System.currentTimeMillis() + TIMEOUT_MS;
while (System.currentTimeMillis() < endTime) {
sleep(50);
}
process.destroy();
The process was not always destroyed if TIMEOUT_MS was too low. Adding an additional sleep() before destroy() fixed it (even though I don't have an explanation why):
Thread.sleep(300);
process.destroy();

How should I execute external commands using multithreading in Java?

I want to run an external programs repeated N times, waiting for output each time and process it. Since it's too slow to run sequentially, I tried multithreading.
The code looks like this:
public class ThreadsGen {
public static void main(String[] pArgs) throws Exception {
for (int i =0;i < N ; i++ )
{
new TestThread().start();
}
}
static class TestThread extends Thread {
public void run() {
String cmd = "programX";
String arg = "exArgs";
Process pr;
try {
pr = new ProcessBuilder(cmd,arg).start();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
pr.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
//process output files from programX.
//...
}
However, it seems to me that only one thread is running at a time (by checking CPU usage).
What I want to do is getting all threads (except the one that is waiting for programX to finish) working? What's wrong with my code?
Is it because pr.waitFor(); makes the main thread wait on each subthread?
The waitFor() calls are not your problem here (and are actually causing the spawned Threads to wait on the completion of the spawned external programs rather than the main Thread to wait on the spawned Threads).
There are no guarantees around when Java will start the execution of Threads. It is quite likely, therefore, that if the external program(s) that you are running finish quickly then some of the Threads running them will complete before all the programs are launched.
Also note that CPU usage is not necessarily a good guide to concurrent execution as your Java program is doing nothing but waiting for the external programs to complete. More usefully you could look at the number of executed programs (using ps or Task Manager or whatever).
Isn't yours the same problem as in this thread: How to wait for all threads to finish, using ExecutorService?

Threading in Java

I am trying to have my main thread spawn off a new thread and, after some time, raise the interrupt flag. When it does so, the spawned thread should see that flag and terminate itself.
The main thread looks something like this:
final Thread t = new Thread()
{
#Override
public void run()
{
f();
}
};
t.start();
try
{
t.join(time);
t.interrupt();
if(t.isAlive())
{
t.join(allowance);
if(t.isAlive())
throw new Exception();
}
}
catch(Exception e)
{
System.err.println("f did not terminate in the alloted time");
}
And the spawned thread has a bunch of the following scattered throughout its code:
if(Thread.interrupted()) return;
When I am in debug mode, everything works perfectly. The interrupt flag is raised by the main thread and is caught by the spawned thread. However, in regular run mode the spawned thread doesn't seem to receive the interrupt flag, no matter how long I set the allowance.
Does anyone know what I am doing wrong?
Note: I am using Ubuntu and I am all-together new to anything Linux. Can the problem be with the OS? I have not tested the code on any other OS.
Here are my guesses:
When main thread calls t.interrupt(); the t thread has already finished execution.
When main thread calls t.interrupt(); in the t thread there are no more calls to check interrupted() flag.
You get the exception as a result of running the code? Do you get the exception you throw in your code after "allowance" time or you got some other like ThreadInterruptedException or similar? Try writing the message of the caught exception...
I suggest you consider using an ExecutorService which is designed to do this sort of thing and could help you in other ways.
ExecutorService service = Executors.newCachedThreadPool();
Future<ResultType> future = service.submit(new Callable<ResultType() {
public ResultType call() throws Exception {
// do soemthing
return (ResultType) ...;
}
);
// do anything you like until you need to result.
try {
ResultType result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException timedOut) {
// handle exception
// cancel the task, interrupting if still running.
result.cancel(true);
} catch (ExecutionException taskThrewAnException) {
// handle exception
}
// when you have finished with the service, which is reusable.
service.shutdown();
Do you have nested checks of Thread.interrupted()? That method clears the interrupted flag, so the second call returns false. You could use isInterrupted() instead.
It looks as though the Thread.interrupted() call is not being reached in f().
The different behaviour you are seeing in Debug and Run modes is likely to be due to a race condition.

Categories

Resources