I have a custom asynchronous method and I know threads are executed randomly, but I want to execute them in order.
I want to solve the problem in the main() method.
I've tried Thread.sleep() but it's not useful.
public static void main(String[] args) throws Exception{
Monster monster = new Monster();
System.out.println(1);
monster.exe();
System.out.println(2);
monster.exe();
System.out.println(3);
monster.exe();
System.out.println(4);
}
Class Monster
class Monster {
public void exe() {
new Thread(() -> {
System.out.println("Monster...: "+ Thread.currentThread().getName());
}).start();
}
}
That's doable, but frankly pointless because such a "parallel" execution even less performant than sequential processing of these tasks.
If you are doing that just as an exercise, that's OK. Otherwise, either don't try to control the execution of these tasks or do it in a single-threaded environment.
For that, you might use method join():
public static void main(String[] args) throws InterruptedException {
Monster monster = new Monster();
System.out.println(1);
Thread thread1 = monster.exe();
thread1.join();
System.out.println(2);
Thread thread2 = monster.exe();
thread2.join();
System.out.println(3);
Thread thread3 = monster.exe();
thread3.join();
System.out.println(4);
}
Each call of join() will block the main thread until another thread (on which this method was invoked) isn't finished its job.
Note: method join() throws InterruptedException which is a checked exception and must be either handled with a try/catch or should be signified in the method declaration. I've deliberately chosen the second option in order to make the code simpler and keep focus on what it is intended to do. But you should know that it's not a good practice to add the throws clause to the declaration of the main() method.
A small change was done to the Monster class (method exe() returns a thread that has been created in order to be able to join on it).
public class Monster {
public Thread exe() {
Thread thread = new Thread(() -> {
System.out.println("Monster...: "+ Thread.currentThread().getName());
});
thread.start();
return thread;
}
}
Output
1
Monster...: Thread-0
2
Monster...: Thread-1
3
Monster...: Thread-2
4
Another way to do it is to extract the codes that you want to execute asynchronously into a separate Runnable :
Runnable newMonstorTask() {
return ()->System.out.println("Monster...: " + Thread.currentThread().getName());
}
And then use CompletableFuture to configure them to execute in order and asynchronously :
CompletableFuture.runAsync(newMonstorTask())
.thenRunAsync(newMonstorTask())
.thenRunAsync(newMonstorTask())
.thenRunAsync(newMonstorTask());
You can use CompletableFuture and then methods like thenApply().
Please look here: https://www.deadcoderising.com/java8-writing-asynchronous-code-with-completablefuture/
Related
In the below code snippet, I notice the following sequence of execution. Why is the control going back to the flow outside the someMethod() before completing the activity in the someTask block? Shouldn't it complete everything inside thread2 before moving to the next line of code as thread2.join() has been invoked?
System.out.prinltn("inside someMethod...");
System.out.println("after thread2 .....");
System.out.prinltn("inside someTask......");
public static void main(String args[]) {
Thread thread1 = new Thread(new someclassimplementingRunnable());
thread1.start();
try {
thread1.join();
Thread thread2 = new Thread(new Runnable() {
public void run() {
someMethod();
}
});
thread2.start();
thread2.join();
System.out.println("after thread2 .....");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("outside try-catch");
}
public static synchronized void someMethod(){
System.out.prinltn("inside someMethod...");
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Runnable someTask = () -> {
System.out.prinltn("inside someTask......");
};
executor.scheduleAtFixedRate(someTask , 0, 2, TimeUnit.SECONDS);
}
it is working as expected. you're just expecting the wrong outcome ;)
Thread2 finishes it's work once the executor starts working, and frankly, its a miracle you get to see "inside someTask" at all, as the executor and it tasks will be garbage collected once "someMethod" finishes working. (i.e. the Executor doesn't stay alive outside of someMethod, and there is no blocking operation at the end of someMethod that waits for the executor to finish).
i would even wager that if you run this code enough times, there will be instances when you won't see the line "inside someTask" because of random OS/process scheduling.
there is no line that makes "someMethod" wait, and so Thread2 finishes its work and it passes .join() and you see the print out "after thread2".
also, remember that the Console is not a synchronic output service. when multiple threads send output to the console, its not guaranteed to appear in the same order. so it is not a good indication of the order of events in a multithreaded environment.
I found the solution and actually its pretty simple, checking the condition while(!executor.isTerminated()) does the job. It ensures the next statements are executed only after the executor has done its job.
I have encountered some challenge, I just want to confirm my knowledge is correct.
How are you going to implement this?
For example, if your program is written in Java the Sieve of Eratosthenes testing should run in one thread, and the Brute Force testing should run concurrently in a separate thread. Finally, your program should report the results of the benchmarking to the screen and exit.
Is it Something like this?
class TestMultitasking4{
public static void main(String args[]){
Thread t1=new Thread(){
public void run(){
System.out.println("task one");
}
};
Thread t2=new Thread(){
public void run(){
System.out.println("task two");
}
};
t1.start();
t2.start();
}
}
Your approach is correct although you might want to avoid creating anonymous classes by extending Thread inside the method.
The next step is to measure the elapsed time inside Runnable and use Thread.join() to wait for the threads to finish so you can display the results. Make sure to use the System.nanoTime() method and not currentTimeMillis() see here why.
If you feel like exploring Java standard library further take a look at things in the java.util.concurrent package e.g. a java.util.concurrent.ExecutorService.
This is incorrect. If you run the program it will just start 2 threads and exit immediately because your main thread will not wait for the termination of t1 and t2.
You should:
Collect the results of your threads (you need callable and futures)
Wait for the threads to terminate (Thread.join is the primitive)
There are lots of ways to achieve this without using Threads directly using higher-level abstractions . The simplest way is probably using CompletableFuture
public static void main(String[] args) {
CompletableFuture<Boolean> future1 = CompletableFuture.supplyAsync(() -> isPrime(42));
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> bruteForcePassword("encrypted"));
var prime = future1.join();
var pwd = future2.join();
System.out.println("Was prime:" + prime);
System.out.println("Password:" + pwd);
}
private static String bruteForcePassword(String s) {
return "Alph#Rome0";
}
private static boolean isPrime(long value) {
return false;
}
There is some weird thing happening. As I enter the synchronized block,I try to print the name of the Thread.After the print statement,I make a husge pause of 100000 seconds.
#Override
public int getNextAvailableVm() {
synchronized(this) {
System.out.println(Thread.currentThread().getName());
try {Thread.sleep(100000000);}catch(Exception exc){}
String dataCenter = dcc.getDataCenterName();
int totalVMs = Temp_Algo_Static_Var.vmCountMap.get(dataCenter);
AlgoHelper ah = (AlgoHelper)Temp_Algo_Static_Var.map.get(dataCenter);
.
.
.
}
}
But as this method is run,name oft the 2 threads are printed.
Thread-11
Thread-13
and it is after this that the long pause occurs. Why is that ? How could the two threads enter the synchronized block,when the first thread has yet not left the block ?
If the two threads are running against the same object then this should not happen.
I would therefore suggest that you are creating a new object for each thread or at least some of the threads are running on different objects.
If you do want multiple objects then you should not use synchronized(this), you should create a static final Object to synchronize on. Please do not sync on this.getClass() as that breaks.
Most likely you are invoking getNextAvailableVm() on different instances of the containing class. Since you are synchronizing on this you will be locking on two different monitors (first thread locks on instance1, second one on instance2).
There are a lot of ways you could correct this:
make the whole method synchronized
synchronize on this.getClass()
define a static object to lock on
use methods from java.util.concurrent.locks to do the locking
These are just some suggestions to address your problem, but to find the right one we would have to know more about your application structure and your requirements.
I guess the below prog, will work like you expected,
Locked on Thread1.Class, Two thread will not execute the method simultaneously
public class Test {
public static void main(String [] args) {
Thread1 t1 = new Thread1();
Thread1 t2 = new Thread1();
t1.start();
t2.start();
}
}
class Thread1 extends Thread{
public void run(){
getNextAvailableVm();
}
public void getNextAvailableVm() {
synchronized(Thread1.class) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
}catch(Exception exc){}
System.out.println(Thread.currentThread().getName());
}
}
}
OUTPUT
Thread-1
Thread-1
Thread-0
Thread-0
my task is to create thread in this order: if A start->start B and C, if B start->start D.
And destroy them in reverse order If D then B. If B and C then A. I hope you get it. I manage to do it but I guess there is better way to do it. Do you have any suggestions?
After your comments i have changed my code and it is much more simply. But now it looks "stupid". I would like to change hardcore of if statements and implementation, any advice? tnx for advice I'm learning with you.
This is my new code:
import java.util.*;
class RobotController implements Runnable{
String name;
public void run() {
Thread t = Thread.currentThread();
System.out.println(t.getName() + " status = " + t.isAlive());
System.out.println(t.getName() + " status = " + t.getState());
}
public static void main(String args[]) throws InterruptedException{
Thread thread_A = new Thread(new RobotController(), "Thread A");
Thread thread_B = new Thread(new RobotController(), "Thread B");
Thread thread_C = new Thread(new RobotController(), "Thread C");
Thread thread_D = new Thread(new RobotController(), "Thread D");
thread_A.start();
thread_A.join();
System.out.println(thread_A.getState());
thread_B.start();
thread_B.join();
System.out.println(thread_B.getState());
thread_C.start();
thread_C.join();
System.out.println(thread_C.getState());
thread_D.start();
System.out.println(thread_D.getState());
}
}
There are some flaws in your code which will make it not to work accordingly sometimes:
You called thread_A.start() and then checked thread_A.isAlive(). Now what if , thread_A is already completed before thread_A.isAlive() condition is checked?.thread_B and thread_C is never started. Your application fails.
Assume that thread_A is not completed and thread_A.isAlive() condition is passed, then starting of thread_B before thread_C is not always guaranteed by Java thread scheduler. Again your application fails.
Assume that thread_B starts before thread_C and if thread_B completes before thread_B.isAlive() is checked then the if condition fails and thread_D is never started. Again your application fails.
Now a point to ponder:
There is no need to check if the thread is alive after its join() method is called. It is an unnecessary runtime overhead.
EDIT
OK, Here is the modified version of code..I hope it would let you understand the dynamics of thread:
class RobotController implements Runnable
{
private final Object lock = new Object();
private void notifyThread()
{
synchronized(lock)
{
lock.notify();
}
}
public void run()
{
synchronized(lock)
{
try
{
System.out.println(Thread.currentThread().getName() + " started");
lock.wait();
System.out.println(Thread.currentThread().getName()+ " stopped");
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
public static void main(String args[]) throws InterruptedException
{
RobotController rca = new RobotController();
RobotController rcb = new RobotController();
RobotController rcc = new RobotController();
RobotController rcd = new RobotController();
Thread thread_A = new Thread(rca,"Thread A");
Thread thread_B = new Thread(rcb,"Thread B");
Thread thread_C = new Thread(rcc,"Thread C");
Thread thread_D = new Thread(rcd,"Thread D");
thread_A.start();
while (thread_A.getState() != Thread.State.WAITING)
{
Thread.sleep(100);
}
thread_B.start();
thread_C.start();
while (thread_B.getState() != Thread.State.WAITING && thread_C.getState() != Thread.State.WAITING)
{
Thread.sleep(100);
}
thread_D.start();
while (thread_D.getState() != Thread.State.WAITING)
{
Thread.sleep(100);
}
rcd.notifyThread();
thread_D.join();
rcc.notifyThread();
thread_C.join();
rcb.notifyThread();
thread_B.join();
rca.notifyThread();
}
}
And here is the output:
Thread A started
Thread B started
Thread C started
Thread D started
Thread D stopped
Thread C stopped
Thread B stopped
Thread A stopped
In multi threading, there is no need of synchronization unless the common data is shared by multiple threads.
In your case, you want to start and stop the threads in a particular order. For this, there is join method in Thread class. This link shows good example of join method.
In my opinion, it is quite strange to use synchronized (lock) in your run method to lock your object. The reason is that in each Thread object has the different lock attribute, which is belong to each object. It means you are trying to lock the different objects. Actually, it doesn't make sense.
Basically, the object that you should apply the synchronized are any shared objects. For example, you need to count something and then you create a class object to share it in your class. In this case, it should be locked while being read or written.
I would like to highlight two points here:
Have a look at thread execution life cycle here. It says that, when start() method is called, thread enters in runnable state and not in running state. When thread enters in running state, that means run() method is getting exexuted. CPU/OS decides the priority of which thread should be transferred from runnable to running thread. E.g. if you call start() method for 4 threads, it is not necessary that they will execute in that particular order. (Running the same program in my pc multiple times gives me different outputs.
In your case, when the condition if(thread_A.isAlive()) is executed, it is possible that the thread A may not be in running state. Hence, the control will not go into if which is not correct.
To correct this behavior, in main, a while loop should implemented which waits until the thread becomes alive and so on.
2 . In your program, you have not assigned names to the threads and you are printing the name in the run() method. In this case, JVM assigns the names to threads in order of their execution e.g. first thread to execute will have name as 'Thread-0' and so on. Hence, we will not be able to identify which thread executed first. Assign the names using setName() method.
I am looking in some puzzles for threads and I can't figure out why the following consistently prints 999999:
class Job extends Thread {
private Integer number = 0;
public void run() {
for (int i = 1; i < 1000000; i++) {
number++;
}
}
public Integer getNumber() {
return number;
}
}
public class Test {
public static void main(String[] args)
throws InterruptedException {
Job thread = new Job();
thread.start();
synchronized (thread) {
thread.wait();
}
System.out.println(thread.getNumber());
}
}
There is no notify on the same lock (and spurious wakeup seem to be ignored).
If a thread finishes does a notify get signalled or something?
How come main prints the result and not get "stuck" waiting?
In the Javadoc for Java 7 Thread.join(long)
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
Using a Thread directly this way is considered bad practical. Note: wait() could end for any number of reasons, possibly spuriously.
Based on a puzzler related to #Voo's comment. The point is you shouldn't play with the internal behaviour of Thread as this is more likely to lead to confusion.
public static String getName() {
return "MyProgram";
}
public static void main(String... args) {
new Thread() {
public void run() {
System.out.println("My program is " + getName());
}
}.start();
}
What does this program print?
For clarification, I have modified your code to this:
Job thread = new Job();
thread.start();
final Object lock = new Object();
synchronized (lock) { lock.wait(); }
System.out.println(thread.getNumber());
Now it blocks. That's a first-hand confirmation of what #Nitram has explained in his answer. If you care to have a look at the Thread implementation code, it will be quite obvious why this is the observed behavior.
NOTE: This answer has been edited extensively.
The reason for this behaviour is, that "someone" is calling notifyAll internally. This "someone" is the JVM itself as you can "see" in the C sources here:
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/f95d63e2154a/src/share/vm/runtime/thread.cpp
In line 1531 the method ensure_join calls notifyAll. This is the counterpart to the wait calls in java.lang.Thread#join (as noted by Marko and others).
ensure_join in turn is called in line 1664 in the method JavaThread::exit.
Since this is "internal bookkeeping" nobody should rely on this behaviour.
Simply put a Thread notifies all waiting threads once the execution of the threads ends. Its not the proposed why to do this, but it works. To synchronize on the end of a thread rather use Thread.join.
A thread object is automatically notified when the thread finishes, that's why the main thread doesn't get stuck.
Well....notify serves purpose of premature notifying to the threads waiting on the locked object. if you don't use Notify ,then certainly when it finishes it releases lock.
So that is equivalent to notify
no it's not..Consider the situation below.
class Job extends Thread {
private Integer number = 0;
public void run() {
synchronized(this) {
for (int i = 1; i < 1000000; i++) {
number++;
}
notify(); //releases lock here and your main thread continues
do sumthing...
do sumthing...
}
}
public Integer getNumber() {
return number;
}
}
if you don't use notify() ...lock will be released only after you do all your sumthings..