Priyanka Taneja
Priyanka Taneja

Reputation: 575

Thread.Yield() not pausing the current thread

As I have read about yield().

It pauses the current thread and execute the next thread, but why its not pausing first thread.

Please explain how it will work.

This is my code

public class MyRunnable implements Runnable {

   public static void main(String[] args) {
      Thread t1 = new Thread(new MyRunnable());
      t1.setName("First");
      t1.start();
      Thread t2= new Thread(new MyRunnable());
      t2.setName("Second");
      t2.start();

      for(int i=0; i<5; i++) {
          System.out.println("Inside main");
      }
   }

   public void run() {
      for(int i=0; i<5; i++) {
          System.out.println(Thread.currentThread().getName());
          Thread.yield();

      }
   }
}

This is my output

Inside main
Inside main
Inside main
Inside main
Inside main
First
First
First
First
First
Second
Second
Second
Second
Second

I have created two threads frst thread and second thread.I want to knw the use of yield() method. As i have read abt yield(). It pauses the current thread and execute the next thread. bt why its not pausing frst thread.Plz expalin how it wil work.

Upvotes: 2

Views: 146

Answers (3)

Solomon Slow
Solomon Slow

Reputation: 27125

[Thread.yield()...] It pauses the current thread and execute the next thread.

No. That's a misunderstanding.

The purpose of Thread.yield() is to create an opportunity for a context switch in a program that runs in a cooperative multitasking system.

I don't know where you can find a system like that these days except maybe on tiny microcontrollers that are too small to be running Java; but once, long ago, cooperative multitasking was more common.

Most modern environments implement preemptive multitasking: The system can switch between threads at any time, and without the threads even knowing that it happened.

In a cooperative multitasking system, the system could only switch between threads when the current thread executed a system call.

But what to do if you wanted a thread to perform some long running background computation, and it did not need to make any system calls? What you would do is add a few yield() calls at strategic points in your computation to give other threads an opportunity to run.

On a modern system, you should not expect Thread.yield() to do anything at all. Maybe, if the system is heavily loaded, it will bump the calling thread to the back of the run queue,... or maybe not. Depends on the whim of the library implementors.

One thing it absolutely does not do (and did not ever do) is "pause" the thread or "wait" for anything. A thread that calls yield() is RUNNABLE before, during, and after the call. Always.

Upvotes: 0

Tagir Valeev
Tagir Valeev

Reputation: 100249

You should almost never use Thread.yield() in your application as documentation says:

It is rarely appropriate to use this method. It may be useful for debugging or testing purposes, where it may help to reproduce bugs due to race conditions

It provides no guarantees whether it will do anything. If you want to establish an ordering in multithreaded program, consider more convenient higher-level primitives like CyclicBarrier or Phaser. For example, if you want the five iterations in the loops in different threads to be synchronized, you may use Phaser like this:

import java.util.concurrent.Phaser;

public class MyRunnable implements Runnable {
    Phaser p;

    public MyRunnable(Phaser p) {
        this.p = p;
    }

    public static void main(String[] args) {
        // We have three parties: main thread and two additional threads
        Phaser p = new Phaser(3); 

        Thread t1 = new Thread(new MyRunnable(p));
        t1.setName("First");
        t1.start();
        Thread t2 = new Thread(new MyRunnable(p));
        t2.setName("Second");
        t2.start();

        for (int i = 0; i < 5; i++) {
            System.out.println("Inside main");
            // notify Phaser that phase is finished and wait other parties before continue
            p.arriveAndAwaitAdvance();
        }
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName());
            // notify Phaser that phase is finished and wait other parties before continue
            p.arriveAndAwaitAdvance();
        }
    }
}

The typical output is the following:

Inside main
Second
First
First
Second
Inside main
Inside main
First
Second
Second
Inside main
First
First
Second
Inside main

So you can see that only after the first iteration in all the threads is finished, the second iteration starts.

Upvotes: 2

Warren Dew
Warren Dew

Reputation: 8928

There are two possible explanations.

First, Thread.yield() is only a hint to the thread scheduler, and does not guarantee that any other threads, let alone all other threads, will run before the current thread is continued. From the Javadoc, "The scheduler is free to ignore this hint" and "It is rarely appropriate to use this method":

http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#yield()

Second, there is a significant amount of system processing to set up a new thread. It may be that the second thread takes long enough to set up that the first thread is permitted to print five lines before the second thread is ready to print.

As a general rule, it is not possible to predict what order threads will run in, and when writing multithreaded code, one should not count on any ordering between processing in different threads, unless you explicitly synchronize the threads.

Upvotes: 1

Related Questions