This question already has answers here:
How to start two process at the same time and then wait both completed?
(3 answers)
Closed 1 year ago.
I'm writing a small program which is supposed to update Firmware on Servers. The way I currently do this is by issuing a command via the ProcessBuilder, executing it and using exitCode = process.waitFor(); to wait until the command is finished.
Some of these Firmware updates can take a few minutes, so when setting up multiple Systems, these Firmware updates can take hours, if done separately.
I have tried creating Threads, while using CyclicBarrier, to ensure that all Firmware Updates are started at the same time. (See: Stackoverflow-Question: How to start two threads at “exactly” the same time
The problem I have spotted with this however, that my program will continue as usual after starting all the threads - which in this case would be to reboot all the systems, which might break them if they are still in the process of updating Firmware.
How could I ensure that all Firmware Updates are done before continuing? I have thought about letting the program sleep for 10-15 minutes, but would like a more reliable approach.
You may use a CountDownLatch in addition to the barrier. Pass the CountDownLatch to each of the thread, once the firmware update is completed, just call the count-down on the latch. In your main thread, after starting all the threads, you may wait by calling latch.await and it will wail till all the other threads finish. You may find a sample here.
You can even use a CountDownLatch with 1 as the count for the starting gun in your case, which precludes the use of the CyclicBarrier.
You need Thread.join() method. Take a look at the example:
public static void main(String[] args) throws InterruptedException {
Runnable sleepTwoSeconds = () -> {
try {
Thread.sleep(2000);
System.out.println("Sleeping finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread t1 = new Thread(sleepTwoSeconds);
t1.start();
Thread t2 = new Thread(sleepTwoSeconds);
t2.start();
t1.join();
t2.join();
System.out.println("Main thread continue.");
}
"How could I ensure that all Firmware Updates are done before continuing?" Main thread will not continue until t1 and t2 are done.
Related
Normal java threads, not daemon threads, seem to execute till end, then main thread finishes, like this:
public static void main(String[] args) {
for(int i = 0; i < 3; ++i){
new Thread(new Runnable(){
#Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("Does this still print?");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
// Java normal threads don't have to call join, they'll still wait to finish.
System.out.println("Main thread start");
}
It will print:
Main thread start
i = 2
i = 0
i = 1
Does this still print?
Does this still print?
Does this still print?
What I saw here is, Java normal threads don't have to call join() and their holder still wait for them to finish. Not sure if my program is too simple to encounter any undefined behavior, could you kindly give some hints when should we use join()?
Thanks.
t.join() does not do anything to thread t in Java. All it does is not return until thread t has finished.
A Java program's main() thread does not wait for any other thread to finish after main() returns. It just ends, and any other non-daemon threads keep running.
Java is not like Go. In Go the program continues only as long as the main thread is alive, in Java any living nondaemon thread keeps the jvm around. In your code the main thread kicks off other threads and then dies. The new threads run to completion even though the main thread is long gone.
For "undefined behavior" I'm guessing you mean data races, or memory visibility issues, where you can't rely on one thing happening before another (for races) or on a value being visible across threads (for vidibility). Calling join does create a happens-before edge. So does calling println (since it acquires a lock). The Java language spec has a list of things that create a happens-before edge.
Calling get on a Future blocks until the future is done similar to how calling join on a Thread blocks until the thread is finished. If you use higher level constructs than just threads, whether it's executor services, CompletableFuture, reactive libraries, actor systems, or other concurrency models, then those are to different extents shielding you from the Thread api and you don't need join so much.
We have an application that's continuously running. Nothing much goes on in the main method except initializing a few background threads. The background threads process socket events as they occur. Apart from the time the socket events are being processed, app remains in the idle state.
Main
Start Thread 1 -> while(socket connection 1 is good) -> process events
Start Thread 2 -> while(socket connection 2 is good) -> process events
Start Thread 3 -> while(socket connection 3 is good) -> process events
Start Thread 4 -> while(socket connection 4 is good) -> process events
while (true); // block main thread from exiting. Otherwise, periodic GC calls kills the app.
As the primary function of my app is to process events and there is not foreground tasks as such. Does blocking main thread is bad in my case? What are some other alternates?
the main thread is just the first thread, and as such is not different from any other thread. If you block it, it means waste of memory occupied by this thread (about 1MB) and nothing more. So I would just return from the main method, if there is no job for this thread.
I noticed a comment in your code: block main thread from exiting. Otherwise, periodic GC calls kills the app. The comment is wrong. GC calls cannot kill the application. I suspect other threads are started in daemon mode, and so the enclosing process does not wait for them to finish.
If you describe in more details when the whole process must end, we could make more sensible advises.
Since your main thread does busy waiting it will require thread scheduler to it (main thread) into list of scheduled threads. And if your machine where you are running your app has less then 4 CPUs then your event processing threads will suffer.
There are a lot of other ways to block your main thread without busy waiting. Thread.join() as mentioned above is one of them. You can also use Future.get(), or ExecutorService.awaitTermination() if you use high level concurrency objects.
Yes, it's a bad design. Use a ExecutorService and add the threads to it.
Blocking in the main method (or from any other thread) should be avoided. The problem you are running into – how to create some threads and keep the JVM running until those threads finish – can be solved in better ways.
If you create a new Thread and call setDaemon(false), then you won't need to do anything with sleeping or waiting. By setting the thread to be non-daemon, the JVM will stay running until that thread completes. From the Javadoc:
The Java Virtual Machine exits when the only threads running are all daemon threads.
Here's an example thread class that tries to sleep for 2 seconds, then prints out a message:
class ExampleThread extends Thread {
#Override
public void run() {
try {
sleep(2000);
System.out.println("done sleeping");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
If you call it like this – by setting daemon to false – you will first see
output thread started, followed by 2 seconds of nothing, then output done sleeping.
public static void main(String[] args) {
ExampleThread t = new ExampleThread();
t.setDaemon(false);
t.start();
System.out.println("thread started");
}
If you replace t.setDaemon(false) with this t.setDaemon(true) – so that the new thread is in fact a daemon thread – then you will see output thread started followed by immediate JVM termination.
I am using an ExecutorService with a fixedThreadPool. I create threads by implementing the Runnable interface. In the run() method, I am calling a time consuming function (let's say Thread.sleep() for now) and finally add an element to a thread safe CopyOnWriteArrayList. I am submitting threads in a for-loop. At the end of the for-loop I shutdown the ExecutorService and await termination.
However, the number of elements in the list does not turn out to be the same as the number of loop-iterations. Where is my mistake in concurrency thinking?
Here is a code example for this problem:
public class TestProgram {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(4);
CopyOnWriteArrayList<String> stringList = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 1000; i++) {
executor.submit(new myThread(stringList));
}
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
System.out.println(Integer.toString(stringList.size()));
}
}
class myThread implements Runnable {
CopyOnWriteArrayList<String> stringList;
public myThread(CopyOnWriteArrayList<String> stringList) {
this.stringList = stringList;
}
public void run() {
String string = new String("test");
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(myThread.class.getName()).log(Level.SEVERE, null, ex);
}
stringList.add(string);
}
}
You're just not giving it enough time to complete. If you want to execute this serially you would need 1000 * 100 milliseconds, which is 100 seconds. You are running it with four threads, so divide that by 4 and you get 25 seconds. You only wait 10 seconds to complete. Increase that to 26 seconds just to be safe and you should see your result.
The ExecutorService#awaitTermination will wait the N number of seconds to complete, if it doesn't complete it will simply return out and continue the execution. To prove my point check the return value
System.out.println(executor.awaitTermination(10, TimeUnit.SECONDS));
The better solution here, is to use a new CountDownLatch(1000), have each Runnable task countDown after it adds to the list and finally have the main thread await completion.
The documentation of ExecutorService.shutdown says the following:
Initiates an orderly shutdown in which previously submitted tasks are
executed, but no new tasks will be accepted. Invocation has no
additional effect if already shut down.
This method does not wait for previously submitted tasks to complete
execution. Use awaitTermination to do that.
This means that you indicate your ExecutorService that it must stop it's services. Thus, this method sets a flag which indicates that the ExecutorService will end soon, which allows the main thread to returns from this method without problems.
ExecutorService.awaitTermination, moreover, reads as follows:
Blocks until all tasks have completed execution after a shutdown
request, or the timeout occurs, or the current thread is interrupted,
whichever happens first.
This means that the main thread will be blocked inside the method, where it will only be returned when the tasks sent to ExecutorService finish. In both cases, the developer intends to end the ExecutorService function. But with awaitTermination, the developer is saying ExecutorService should be terminated regardless of their tasks have been carried out or not.
As each task takes at least 100 milliseconds to complete, no one will possibly be completed because ExecutorService has a tolerance of only 10 milliseconds for completion of all it's tasks.
There is no point in calling shutdown and awaitTermination at the same time (or preceded by another). According to your code, shutdown has no effect. If you want your tasks to become completed, and that ExecutorService is terminated without caring if your main thread will continue, just use shutdown. If you do not want your main thread to be blocked, and simply want to end with ExecutorService, use shutdownNow.
If, on the other hand, you want your main thread to wait for the execution of your tasks without a certain time to be specified, you may have to use Java Synchronizers. Some of Java Synchronizers are as follow:
Latches
FutureTasks
Semaphores
Barriers
For your case, I believe you can use CountDownLatch. Make a new CountDownLatch object have the number of tasks running on your ExecutorService. As they are completed, the count is decreased, and so, your main thread can expect completion and continue after all.
I hope you have understood and you can do what you want. If you have further questions, the documentation of CountDownLatch demonstrates perfectly how you can synchronize tasks. Good luck.
In that code snippet one issue will be there.
executor.awaitTermination(10, TimeUnit.SECONDS);
Here it will wait for 10 seconds after that it will break.
You will try following snippet.
while (true) {
if(executor.awaitTermination(10, TimeUnit.SECONDS))
break;
}
when I use Thread.sleep();, it pauses my entire program. Is there anything that pauses one class without using multithreading?
You don't pause classes, you pause threads. In the moment you pause your only thread, you pause you entire application as well. So there is no way to pause your only thread and expect the application will continue to run. You would need more than one thread if you expect your application do more than just waiting.
I think you're confusing some concepts here. Classes and Objects do not run. Threads run, and what they run are the instructions (code) defined by classes and objects.
So no, you cannot pause a Class or Object, only a Thread. Moreover, if your application is single threaded, then you only have a "main" thread, and if you pause that thread then your whole application will pause.
You can't pause a "class" per se. A class is just a "dead" container.
What you can do is pause a thread or a task.
Typically, you would create a separate thread to run the task you want to pause, and pause it when you like - because it runs in a separate thread, it will not hang you whole program.
See this simple example which you can run to better understand how threads can run in parallel:
public static void main(String[] args) throws InterruptedException {
Runnable lazyTask = new Runnable() {
#Override
public void run() {
System.out.println("Lazy: I feel like sleeping for a second");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
System.out.println("Lazy: I feel better now");
}
};
new Thread(lazyTask).start();
//Let's wait a bit until the lazy task goes to sleep
Thread.sleep(100);
//now you can do something that will not hang
System.out.println("Main: I'm sleeping too, but only half a second");
Thread.sleep(500);
System.out.println("Main: And I can continue my job while that lazy task is still asleep");
}
No. You cannot. You have the main thread . Sleep will pause it. If you want stop run something without affect the main thread you need to fork it from the main thread , by use addiotnal thread
I have an assignment with threads and I cant have the threads go into busy wait state.
How do I know if a thread is in blocking state or in busy wait? Is there a command that checks it?
In the program I have 2 matrices and I need to transform them. So I have a transform thread and the code is as follows:
transformThread transformThreadFirst = new transformThread(firstMat, n);
transformThread transformThreadSecond = new transformThread(secondMat, n);
transformThreadFirst.start();
transformThreadSecond.start();
try
{
transformThreadFirst.join();
transformThreadSecond.join();
}
catch(InterruptedException e)
{
}
Any of the threads will be in busy wait or is it ok? Or you have a better solution?
Also in the run of the transformThread I do not use any yield, just 2 for loops and thats it, just the transform action..
Busy waiting is doing something repeatedly until another operation finishes. Something like this:
// The next line will be called many many times
// before the other thread finishes
while (otherThread.getState() == Thread.State.RUNNABLE) {}
So your code is not busy waiting, the current thread will block until the transformThreadFirst finishes and then block until transformThreadSecond is done.
There's a jstack utility.
use it as jstack <pid>, passing the process id of your running jvm.
It would display what every thread in that app is doing, together with thread status (RUNNING, WAITING, BLOCKED).
It is bundled with JDK and located in its bin/