Thread.Join Blocks the Main Thread

If join blocks the main thread, why it doesn't block in loop?

First of all:

The join() method of a Thread instance can be used to "join" the start of a thread's execution to the end of another thread's execution

That is a misconception: this has nothing to do with starting Threads. Join only does this: a running thread will wait until the other thread has ended.

When you do someThread.join(), then the thread invoking that method will wait until someThread has ended!

But all the threads are joined in parallel.

Yes, because they are all done.

Your threads do all the exact same thing, so besides a few nanoseconds here or there (which are mostly invalidated due to the fact that writing to System.out effectively synchronizes stuff anyway) they all need the same amount of time.

So by the time you join the first thread ... the other two threads will be done. So the first call to join() makes the "main" thread wait for the first thread to end, and the subsequent calls happen "instantly", because these threads are done, too.

In order to delay things, make the number of loops a parameter of your MultiThreading class, and then ensure that your threads will require for different amounts of time. If Thread-0 does 10 loops, and Thread-1 goes 20, and the Thread-2 will do 30, you will see that each join does in fact wait for the corresponding thread to end.

Long story short: you start all your threads immediately, thus they instantly start running in parallel. The later join call simply delays the main thread from progressing, until each of the worker threads has ended.

join() blocks continuation of main thread

The entire point of join() is to block until the other thread exits. Just get rid of it. Why'd you add it in the first place?

C# Thread.Join() blocks the main thread

You don't want to block and wait for the other thread to finish. That is what Thread.Join() does.

Instead you would want to perform a thread cancellation. MSDN Managed Thread Cancellation

The .join() method block UI thread even when called on a new thread

Since I see no evidence of any blocking operations, this is all you need:

fun btn(view: android.view.View) {
binding.firstText.text = ""
viewModelScope.launch {
delay(10_000)
val a = "I am the guy who comes 10 secs later\nDid you miss me?"
Log.d(TAG, "btn: $a")
binding.firstText.text = a
}
}

If you do intend to make blocking operations instead of that delay(10_000), then you can add this:

fun btn(view: android.view.View) {
binding.firstText.text = ""
viewModelScope.launch {
val a = withContext(Dispatchers.IO) {
blockingOperation()
"I am the guy who comes 10 secs later\nDid you miss me?"
}
Log.d(TAG, "btn: $a")
binding.firstText.text = a
}
}

Note there's the viewModelScope, this won't work unless you're inside a ViewModel class. You can use GlobalScope instead to try things out, but this is not a production-worthy solution as it leads to memory leaks at runtime whenever you trigger many such actions while the previous ones are in progress (and they will be because there's nothing cancelling them).

does threading.join() block the thread that's called it?

Your program starts the two threads before waiting for t1 and t2 to finish, that is why you have 30 before 19 in your console.

While the programs wait for t1 to finish, t2 is still running and printing to the console.

If for any reason you want to use multithreading and have t2 waiting for t1 to finish before starting, you can use the following code :

import threading
import time # Useful for adding some delay in order to visualize what is happening

def count(start, end):
for i in range(start, end):
print(i)
time.sleep(500) # Add some delay to see clearly what is happening

t1 = threading.Thread(target=count, args=[10, 20])
t2 = threading.Thread(target=count, args=[30, 40])

# This starts the two threads and wait for bot of them to finish
#t1.start()
#t2.start()
#
#t1.join()
#t2.join()
#

# This starts one thread and wait for it to finish before starting the other
t1.start()
t1.join() # We wait for t1 to finish

t2.start() # Then we start the second thread (t2)
t2.join()

NB : You can't start the same thread 2 times so make sure to comment/delete my part if you want to test the code with the 2 threads running at the same time.

EDIT : By program I mean main thread

Java Thread is blocked in join()

Without running it...

  • The close() method holds lock at the time it calls thread.join() and waits on thread (forever)
  • thread is waiting to reacquire lock so cannot run

Both are now waiting on each other, this is a deadlock. Try moving the Thread.join() after the synchronized block:

    public void close() throws InterruptedException {
run = false;
synchronized (lock) {
lock.notify();
System.out.println("Thread will join " + thread.isInterrupted());
}
thread.join();
System.out.println("Thread after join");
}

std::thread::join blocks indefinitely out of main

Yes it is the same bug as in the referenced link since your example also hangs on _Thrd_join. You could be interrested in this question which contains a far more detailed analysis.

Thread.join blocks the main thread

You simply accumulate the threads in another container, then join them one-by-one after they've all been created:

my_threads = []
for i in 1..100 do
puts "Creating thread #{i}"
my_threads << Thread.new(i) do |j|
sleep 1
puts "Thread #{j} done"
end
end
puts "#{Thread.list.size} threads"

my_threads.each do |t|
t.join
end

You also can't bind the thread to the i variable because i gets constantly overwritten, and your output will be 100 lines of "Thread 100 done"; instead, you have to bind it to a copy of i, which I have cleverly named j.



Related Topics



Leave a reply



Submit