Reputation: 19582
The method Thread.yield
:
Causes the currently executing thread object to temporarily pause and allow other threads to execute.
So in the following code:
public class Test implements Runnable {
private int stopValue;
public Fib(int stopValue){
this.stopValue = stopValue;
}
@Override
public void run() {
System.out.println("In test thread");
for(int i = 0; i < stopValue; i++){
c = i + 1;
}
System.out.println("Result = "+c);
}
public static void main(String[] args){
int defaultStop = 1024;
if(args.length > 0){
defaultStop = Integer.parseInt(args[0]);
}
Thread a = new Thread(new Fib(defaultStop));
System.out.println("In main");
a.setDaemon(true);
a.start();
Thread.yield();
System.out.println("Back in main");
}
}
I expect that I should see:
In main
then In test thread
and the rest would be undefined. But I don't understand why sometimes I only see:
In main
and Back in main
and not any print statement from Test
thread?
Upvotes: 1
Views: 307
Reputation: 116888
@Peter's answer is a good one but I wanted to add some additional information as an answer.
First, as mentioned elsewhere, the a.setDaemon(true)
causes the JVM to not wait for the Thread a
to finish before quitting. If your real question is how to make sure that the Thread a
does it's work before the JVM shuts down then removing the setDaemon(true)
may be the solution. Daemon threads can be killed when the JVM exits. Non-daemon threads will be waited for. So the main()
method might return and the main thread might exit but your Thread a
would still run to completion.
In terms of Thread.yield()
, as you mention, the javadocs state:
Causes the currently executing thread object to temporarily pause and allow other threads to execute.
This, however, is somewhat misleading. For example, if you have 2 threads running and 2 or more processors on your architecture, then the yield()
will effectively be a no-op. There are no other threads in the run queue that are waiting for processor resources so the main thread would be quickly rescheduled and would continue running with minimal pause.
Even if your are running on a single CPU system and your Main
does yield()
, your Thread a
goes to do a System.out
which is IO. The IO may block causing thread execution to switch back to Main
immediately.
When it comes down to it, only in very unique circumstances is a use of yield()
necessary. I've done a lot of multithreading programming and I've never used it. Trusting that the JVM thread scheduling will "do the right thing" in terms of time slicing is always recommended unless you have profiler output or expert advice to the contrary.
Upvotes: 0
Reputation: 533570
yield() is a hint to the OS scheduled but doesn't provide any guarantees in terms of scheduling. It doesn't always pause very long. If you call it repeatly it might only take a few micro-seconds.
Starting a thread takes time and even if you main thread pauses briefly, it may finish before the background thread starts.
As you can see, yield() pauses very briefly.
long start = System.nanoTime();
long runs = 20000000;
for (int i = 0; i < runs; i++)
Thread.yield();
long time = System.nanoTime() - start;
System.out.printf("Thread.yield() took an average of %,d ns.%n", time / runs);
prints
Thread.yield() took an average of 148 ns.
by comparison, System.nanoTime take longer on my machine.
long start = System.nanoTime();
long runs = 20000000;
for (int i = 0; i < runs; i++)
System.nanoTime();
long time = System.nanoTime() - start;
System.out.printf("System.nanoTime() took an average of %,d ns.%n", time / runs);
prints
System.nanoTime() took an average of 656 ns.
Both times will vary from OS to OS and machine to machine.
Upvotes: 4
Reputation: 43
Try replacing your Thread.yield() with:
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
System.out.println(ex);
}
Upvotes: 0
Reputation: 24867
Well, the yield() probably does nothing at all because the set of ready threads is less than the number of cores, in which case both threads can run anyway and main() will just continue to run on to the core it was running while the OS issues, (quite likely queues), a call to its intercore driver to run the new thread on another CPU core. Then there's the interaction with 'System.out.println' - an output stream call that is probably protected with a mutex.
I cannot quickly find any understandable explanation of what yield() actually does in differing environments/CPU/OS - one of the reasons I have never used it. The other is that I can't think of any use for it no matter how it works.
Upvotes: 2
Reputation: 19443
The main process might have exited before the thread got a chance to start. There is no guarantee that Thread.yield()
will force the thread to run in any particular time. If the thread did not start, then the setDaemon()
would have no effect.
Upvotes: 0