I have an example that seems strange to me.
public class Join {
public static void main(String[] args) {
Thread t1 = new Thread(
new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
);
Thread t2 = new Thread(t1);
t1.setName("t1");
t2.setName("t2");
t1.start();
try {t1.join();} catch (InterruptedException ie) {}
t2.start();
}
}
We'll see printed only t1.
If we'll comment "t1.join", we'll se the expected output (t1 t2).
Why ?
The second thread is created incorrectly:
Thread t2 = new Thread(t1);
I can't support it by documentation, but in the source code of Thread.run() I see:
if (target != null) {
target.run();
}
Where target is Runnable instance. When the Thread is done, it clears the target variable:
private void exit() {
//...
target = null;
This means that when the first thread is done (join() method) it clears the target and the second thread does nothing. When join() is removed, both access the same target of t1 (race condition).
TL;DR
Never create a thread using another thread instance (even though it implements Runnable). Instead create a separate Runnable and pass it:
final Runnable run = new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
Thread t1 = new Thread(run, "t1");
Thread t2 = new Thread(run, "t2"); //new Thread(t1, "t2"); is incorrect!
t1.start();
t2.start();
You don't need any join()s here, by default these are non-daemon threads.
See also
Java Threading Basics (discussion on #2)
Add before t2.start();:
System.out.println("t1 is alive: " + t1.isAlive());
If main thread is waiting for t1 to die then t2.start() can not run t1's run method. Otherwise, without waiting for t1 to die, t2 can run t1's run method.
This is because main thread waits for t1 to die when you call t1.join().
And when you do this
Thread t2 = new Thread(t1);
you are passing t1 as target object whose run method is called.
Related
I have a Thread worker class Java, which is initiated several times (Lets say 10 instances). Now I want to stop these running threads one by one in the order they a created (First in first). All these thread objects are stored in an ArrayList. Could anyone help.
Thanks in advance
Lee
Thread.join() method is used for the same purpose. Docs here.
Lets say tou have Thread T1, T2 and T3.
To finish T3 before T2 and t2 before T1 you need to call T2.join() from T1 and T3.join() from T2. You can do something like below-
public class ThreadSync extends Thread {
Thread waitForThread;
public void setWaitForThread(Thread waitForThread) {
this.waitForThread = waitForThread;
}
#Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " Thread Started");
if(waitForThread != null)
waitForThread.join();
System.out.println(Thread.currentThread().getName() + " Thread Terminating");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String args[]){
Thread t1 = new ThreadSync();
t1.setName("T1");
Thread t2 = new ThreadSync();
t2.setName("T2");
Thread t3 = new ThreadSync();
t3.setName("T3");
((ThreadSync)t3).setWaitForThread(t2);
((ThreadSync)t2).setWaitForThread(t1);
t1.start();
t2.start();
t3.start();
}
}
Output is
T1 Thread Started
T3 Thread Started
T2 Thread Started
T1 Thread Terminating
T2 Thread Terminating
T3 Thread Terminating
MyThread[] arr = new Thread[10];
for(int i = 0; i < arr.length; i++) {
arr[i] = new MyThread();
arr[i].start();
}
for(int i = 0; i < arr.length; i++) {
arr[i].join();
}
What this code does is useless (implement yiur own usage). join() waits for the thread to die correctly (reach end of run()). If you want to forcely kill a thread, use stop(), but it is deprecated and unsafe.
In most cases, if I manage my own threads, I have some kind of flag (e.g. a volatile boolean or AtomicBoolean) that is checked on every run by a thread. E.g.
private volatile stop = false;
void stop(){
stop = true;
}
class Worker implements Runnable{
public void run(){
while(!stop){
... your logic
}
}
}
You can interrupted your threads if your threads are potentially blocking for something and you need to let them break free:
void stop(){
stop = true;
for(Thread thread: threads){
thread.interrupt();
}
}
I am starting to learn threads. I have tried different types of thread creation. From the below code you can see the thread t4, target is new instance of Mythread1 & thread name is "Thread4".
But when I see the output I am not able to find the Thread name "Thread 4" instead I get the name "Thread-4". But this is a naming convention for a default thread name.
I am not able to understand what's wrong. I am sure its very basic mistake. Kindly correct me.
class MyThread1 extends Thread {
MyThread1() {
}
public MyThread1(String nameIn) {
super(nameIn);
}
public void run() {
System.out.println(this.getName());
}
}
class MyThread2 implements Runnable {
Thread ownThread;
public MyThread2() {
}
public MyThread2(String nameIn) {
ownThread = new Thread(this, nameIn);
}
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class ThreadCreation {
public static void main(String[] args) {
//Execution type1, as direct thread object
MyThread1 t1 = new MyThread1();
Thread t2 = new MyThread1();
Thread t3 = new Thread(new MyThread1());
Thread t4 = new Thread(new MyThread1(), "Thread4");
Thread t5 = new MyThread1("Thread5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
//Execution type2, pass the runnable object to thread constructor
Thread t11 = new Thread(new MyThread2());
Thread t22 = new Thread(new MyThread2(), "Thread22");
MyThread2 t33 = new MyThread2("Thread33");
t11.start();
t22.start();
t33.ownThread.start();
}
}
Output:
Thread-0
Thread-2
Thread-1
Thread-4
Thread5
Thread22
Thread-5
Thread33
But when I see the output I am not able to find the Thread name "Thread 4" instead I get the name "Thread-4". But this is a naming convention for a default thread name.
Your problem is in code like this:
Thread t4 = new Thread(new MyThread1(), "Thread4");
This code is using MyThread1 as a Runnable and not as a thread. So when the run() method is called you are then calling getName() on the MyThread1 instance and not on the thread that is actually running and calling your run() method and whose name is "Thread4". That is why the MyThread2 class works because it is using Thread.currentThread() to display the true running thread's name.
When you create a thread, either you need to extend Thread and start it as new MyThread1("Thread4") or implement Runnable and do new Thread(new MyRunnable1(), "Thread4");. Implementing of Runnable is the recommended pattern since it allows you to extend other classes.
You never want to do something like new Thread(new ClassThatExtendsThread(), "name"). That creates a fake Java Thread instance that is going to just confuse you.
In your MyThread1 you print the name of the thread object the method is in. Since you don't specify another name when creating the object, a sequential name "Thread-4" is generated for you.
You should either print the name of the executing thread, like in MyThread2, or create the MyThread1 object with a name:
Thread t4 = new Thread(new MyThread1("Thread4"));
I tried to create a five threads, accordingly if one thread invokes the synchronized method on one object(objsyn in this case) then all other threads should wait till the thread finishes with the object. So the output should come from thread 1 to thread 5 in order. But the output is coming out of order.
class synctest extends Thread
{
public synchronized void display()
{
try{Thread.sleep(5000*((long)(Math.random())));}
catch(Exception e){}
System.out.println("From synchornized thread "+ Thread.currentThread().getName());
}
public synchronized void run()
{
synctest objsyn = new synctest();
objsyn.display();
}
public static void main(String args[])
{
synctest objsy = new synctest();
Thread t1 = new Thread(objsy,"Thread 1");
Thread t2 = new Thread(objsy,"Thread 2");
Thread t3 = new Thread(objsy,"Thread 3");
Thread t4 = new Thread(objsy,"Thread 4");
Thread t5 = new Thread(objsy,"Thread 5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
Thread execution order is not guaranteed. Synchronization make sure only one thread executing that block of code at a point of time, it doesn't care whether it is first thread (or) second thread.
If you want really execute a particular logic in order, then you don't really need threading. Remember that when you start a thread, it will be separate thread from main thread. May be answers for this question help you.
In this code, what does the two joins and break mean? t1.join() causes t2 to stop until t1 terminates?
Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread t2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
try {
t1.join();
t2.join();
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
What does this thread join code mean?
To quote from the Thread.join() method javadocs:
join() Waits for this thread to die.
There is a thread that is running your example code which is probably the main thread.
The main thread creates and starts the t1 and t2 threads. The two threads start running in parallel.
The main thread calls t1.join() to wait for the t1 thread to finish.
The t1 thread completes and the t1.join() method returns in the main thread. Note that t1 could already have finished before the join() call is made in which case the join() call will return immediately.
The main thread calls t2.join() to wait for the t2 thread to finish.
The t2 thread completes (or it might have completed before the t1 thread did) and the t2.join() method returns in the main thread.
It is important to understand that the t1 and t2 threads have been running in parallel but the main thread that started them needs to wait for them to finish before it can continue. That's a common pattern. Also, t1 and/or t2 could have finished before the main thread calls join() on them. If so then join() will not wait but will return immediately.
t1.join() means cause t2 to stop until t1 terminates?
No. The main thread that is calling t1.join() will stop running and wait for the t1 thread to finish. The t2 thread is running in parallel and is not affected by t1 or the t1.join() call at all.
In terms of the try/catch, the join() throws InterruptedException meaning that the main thread that is calling join() may itself be interrupted by another thread.
while (true) {
Having the joins in a while loop is a strange pattern. Typically you would do the first join and then the second join handling the InterruptedException appropriately in each case. No need to put them in a loop.
This is a favorite Java interview question.
Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread e2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
try {
t1.join(); // 1
t2.join(); // 2 These lines (1,2) are in in public static void main
break;
}
}
t1.join() means, t1 says something like "I want to finish first". Same is the case with t2. No matter who started t1 or t2 thread (in this case the main method), main will wait until t1 and t2 finish their task.
However, an important point to note down, t1 and t2 themselves can run in parallel irrespective of the join call sequence on t1 and t2. It is the main/daemon thread that has to wait.
join() means waiting for a thread to complete. This is a blocker method. Your main thread (the one that does the join()) will wait on the t1.join() line until t1 finishes its work, and then will do the same for t2.join().
A picture is worth a thousand words.
Main thread-->----->--->-->--block##########continue--->---->
\ | |
sub thread start()\ | join() |
\ | |
---sub thread----->--->--->--finish
Hope to useful, for more detail click here
When thread tA call tB.join() its causes not only waits for tB to die or tA be interrupted itself but create happens-before relation between last statement in tB and next statement after tB.join() in tA thread.
All actions in a thread happen-before any other thread successfully returns from a join() on that thread.
It means program
class App {
// shared, not synchronized variable = bad practice
static int sharedVar = 0;
public static void main(String[] args) throws Exception {
Thread threadB = new Thread(() -> {sharedVar = 1;});
threadB.start();
threadB.join();
while (true)
System.out.print(sharedVar);
}
}
Always print
>> 1111111111111111111111111 ...
But program
class App {
// shared, not synchronized variable = bad practice
static int sharedVar = 0;
public static void main(String[] args) throws Exception {
Thread threadB = new Thread(() -> {sharedVar = 1;});
threadB.start();
// threadB.join(); COMMENT JOIN
while (true)
System.out.print(sharedVar);
}
}
Can print not only
>> 0000000000 ... 000000111111111111111111111111 ...
But
>> 00000000000000000000000000000000000000000000 ...
Always only '0'.
Because Java Memory Model don't require 'transfering' new value of 'sharedVar' from threadB to main thread without heppens-before relation (thread start, thread join, usage of 'synchonized' keyword, usage of AtomicXXX variables, etc).
Simply put:
t1.join() returns after t1 is completed. It doesn't do anything to thread t1, except wait for it to finish.
Naturally, code following
t1.join() will be executed only after
t1.join() returns.
From oracle documentation page on Joins
The join method allows one thread to wait for the completion of another.
If t1 is a Thread object whose thread is currently executing,
t1.join() : causes the current thread to pause execution until t1's thread terminates.
If t2 is a Thread object whose thread is currently executing,
t2.join(); causes the current thread to pause execution until t2's thread terminates.
join API is low level API, which has been introduced in earlier versions of java. Lot of things have been changed over a period of time (especially with jdk 1.5 release) on concurrency front.
You can achieve the same with java.util.concurrent API. Some of the examples are
Using invokeAll on ExecutorService
Using CountDownLatch
Using ForkJoinPool or newWorkStealingPool of Executors(since java 8)
Refer to related SE questions:
wait until all threads finish their work in java
For me, Join() behavior was always confusing because I was trying to remember who will wait for whom.
Don't try to remember it that way.
Underneath, it is pure wait() and notify() mechanism.
We all know that, when we call wait() on any object(t1), calling object(main) is sent to waiting room(Blocked state).
Here, main thread is calling join() which is wait() under the covers. So main thread will wait until it is notified.
Notification is given by t1 when it finishes it's run(thread completion).
After receiving the notification, main comes out of waiting room and proceeds it's execution.
Hope it helps!
package join;
public class ThreadJoinApp {
Thread th = new Thread("Thread 1") {
public void run() {
System.out.println("Current thread execution - " + Thread.currentThread().getName());
for (int i = 0; i < 10; i++) {
System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
Thread th2 = new Thread("Thread 2") {
public void run() {
System.out.println("Current thread execution - " + Thread.currentThread().getName());
//Thread 2 waits until the thread 1 successfully completes.
try {
th.join();
} catch( InterruptedException ex) {
System.out.println("Exception has been caught");
}
for (int i = 0; i < 10; i++) {
System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
public static void main(String[] args) {
ThreadJoinApp threadJoinApp = new ThreadJoinApp();
threadJoinApp.th.start();
threadJoinApp.th2.start();
}
//Happy coding -- Parthasarathy S
}
The join() method is used to hold the execution of currently running thread until the specified thread is dead(finished execution).
Why we use join() method?
In normal circumstances we generally have more than one thread, thread scheduler schedules the threads, which does not guarantee the order of execution of threads.
Let's take a look at an example, create new project and copy the following code:
this is activity_main.xml code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btn_without_join"
app:layout_constraintTop_toTopOf="parent"
android:text="Start Threads Without Join"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btn_with_join"
app:layout_constraintTop_toBottomOf="#id/btn_without_join"
android:text="Start Threads With Join"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tv"
app:layout_constraintTop_toBottomOf="#id/btn_with_join"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
And this is code for MainActivity.java:
public class MainActivity extends AppCompatActivity {
TextView tv;
volatile String threadName = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.tv);
Button btn_without_join = findViewById(R.id.btn_without_join);
btn_without_join.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
withoutJoin();
}
});
Button btn_with_join = findViewById(R.id.btn_with_join);
btn_with_join.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
withJoin();
}
});
}
private void withoutJoin()
{
tv.setText("");
Thread th1 = new Thread(new MyClass2(), "th1");
Thread th2 = new Thread(new MyClass2(), "th2");
Thread th3 = new Thread(new MyClass2(), "th3");
th1.start();
th2.start();
th3.start();
}
private void withJoin()
{
tv.setText("");
Thread th1 = new Thread(new MyClass2(), "th1");
Thread th2 = new Thread(new MyClass2(), "th2");
Thread th3 = new Thread(new MyClass2(), "th3");
th1.start();
try {
th1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
th2.start();
try {
th2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
th3.start();
}
class MyClass2 implements Runnable{
#Override
public void run() {
Thread t = Thread.currentThread();
runOnUiThread(new Runnable() {
public void run() {
tv.setText(tv.getText().toString()+"\n"+"Thread started: "+t.getName());
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
tv.setText(tv.getText().toString()+"\n"+"Thread ended: "+t.getName());
}
});
}
}
}
This will be the result if you press first button (Start Threads Without Join):
And this will be the result if you press second button (Start Threads With Join):
let's say our main thread starts the threads t1 and t2. Now, when t1.join() is called, the main thread suspends itself till thread t1 dies and then resumes itself.
Similarly, when t2.join() executes, the main thread suspends itself again till the thread t2 dies and then resumes.
So, this is how it works.
Also, the while loop was not really needed here.
I am studying the Threads in java.
I just want a simple example which explains the use of join() in Thread. I have seen this link..
Understanding join() method example
But still not able to understand the concept.
Can anybody explain me the concept of using the join() in Thread.
Any explanation retlated to this will be very helpful to me.
Thanks.
The simplest explanation I can come up is that join makes the caller thread wait for the completion of specified thread.
Say if you have a "main thread" and "thread A", if from the main thread you call A.join(), the main thread will wait until thread A finishes.
The java se manual page about concurrency should help you here: http://docs.oracle.com/javase/tutorial/essential/concurrency/join.html
Thread.join() causes the current thread to wait for the thread you call join() on to die before it resumes execution.
Thread.join() blocks (does not return) until the thread you joined on has finished.
This is not the only way to wait for a thread to finish, but it is the most CPU-usage friendly way. Imagine if you had a loop like this (pseudocode):
while(!thread.isAlive())
{
Sleep(1);
}
This supposedly does the same thing... but, 1000 times per second, it will wake up, check the variable and go back to sleep. This means 1000 context switches (which are expensive) and the program will be slower as a result. This is called 'spinlocking' or 'busywaiting' and is frowned upon in programming as it consumes CPU for no reason.
I did some experiment and here is the result: 1. first started thread t3. 2. started t1 then 3. created t2 and t2 joinned the running thread t1.
By definition, t2 should wait for t1 to die and then it should start.
Observation: I called wait on t1, so t1 is paused but not died but I see then t2 is started why ?
public class TestThreadJoin {
public static void main(String[] args) {
final Thread t3 = new Thread(new Runnable() {
public void run() {
System.out.println("R3");
}
});
t3.start();
final Thread t1 = new Thread(new Runnable() {
public void run() {
System.out.println("R1 before");
try {
perform();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("R1 after");
}
private void perform() throws InterruptedException {
synchronized(this){
wait(5000);
}
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
public void run() {
System.out.println("R2");
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
}
}