1. Overview
In this tutorial, we’ll explore the method yield() in Thread class.
We’ll compare it with other concurrency idioms available in Java and eventually explore the practical applications of it.
2. Synopsis of yield()
As the official documentation suggests, yield() provides a mechanism to inform the “scheduler” that the current thread is willing to relinquish its current use of processor but it’d like to be scheduled back soon as possible.
The “scheduler” is free to adhere or ignore this information and in fact, has varying behavior depending upon the operating system.
The following code fragment displays two threads at same priority yielding after each schedule:
public class ThreadYield {
public static void main(String[] args) {
Runnable r = () -> {
int counter = 0;
while (counter < 2) {
System.out.println(Thread.currentThread()
.getName());
counter++;
Thread.yield();
}
};
new Thread(r).start();
new Thread(r).start();
}
}
When we try to run the above program multiple times, we get different results; some of them are mentioned below:
Run 1:
Thread-0
Thread-1
Thread-1
Thread-0
Run 2:
Thread-0
Thread-0
Thread-1
Thread-1
So as you can see the behavior of yield() is non-deterministic and platform dependent as well.
3. Comparing with Other Idioms
There are other constructs for affecting the relative progression of threads. They include wait(), notify() and notifyAll() as part of Object class, join() as part of Thread class, and sleep() as part of Thread class.
Let’s see how do they compare to yield().
3.1. yield() vs wait()
- While yield() is invoked in the context of the current thread, wait() can only be invoked on an explicitly acquired lock inside a synchronized block or method
- Unlike yield(), it is possible for wait*()* to specify a minimum time period to wait before any attempt to schedule the thread again
- With wait() it is also possible to wake the thread anytime through an invocation of notify() or notifyAll() on the concerned lock object
3.2. yield() vs sleep()
- While yield() can only make a heuristic attempt to suspend the execution of the current thread with no guarantee of when will it be scheduled back, sleep() can force the scheduler to suspend the execution of the current thread for at least the mentioned time period as its parameter.
3.3. yield() vs join()
- The current thread can invoke join() on any other thread which makes the current thread wait for the other thread to die before proceeding
- Optionally it can mention a time period as its parameter which indicates the maximum time for which the current thread should wait before resuming
4. Usage for yield()
As the official documentation suggests it’s rarely necessary to use yield() and hence should be avoided unless very clear with the objectives in the light of its behavior.
Nonetheless, some of use for yield() include designing concurrency control constructs, improving system responsiveness in a compute-heavy program etc.
However, these usages must be accompanied by detailed profiling and benchmarking to ensure the desired outcome.
5. Conclusion
In this brief article, we discussed the yield() method in the Thread class and saw its behavior and limitations through a code fragment.
We also explored its comparison against other concurrency idioms available in Java and finally looked upon some of the use cases where yield() might be useful.
As always, you can check out the examples provided in this article over on GitHub.