yield()的主要用途是什么?它与join()和interrupt()有什么不同?
我对Java中yield()
方法的使用有点困惑,特别是在下面的示例代码中。 我也读过yield()是用来阻止线程执行的。
我的问题是:
-
我相信下面的代码在使用
yield()
和不使用yield()
时会yield()
相同的输出。 它是否正确? -
事实上,
yield()
的主要用途是什么? -
yield()
与join()
和interrupt()
方法有什么不同?
代码示例:
public class MyRunnable implements Runnable { public static void main(String[] args) { Thread t = new Thread(new MyRunnable()); t.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("Inside run"); Thread.yield(); } } }
使用上面的代码获得相同的输出,使用yield()
和不使用yield()
:
Inside main Inside main Inside main Inside main Inside main Inside run Inside run Inside run Inside run Inside run
来源: http : //www.javamex.com/tutorials/threads/yield.shtml
视窗
在Hotspot实现中,
Thread.yield()
工作方式在Java 5和Java 6之间发生了变化。在Java 5中,
Thread.yield()
调用Windows API调用Sleep(0)
。 这具有清除当前线程的量子并将其放到队列末尾以达到其优先级的特殊效果。 换句话说,具有相同优先级(以及更高优先级)的所有可运行线程将有机会在下一个给定CPU时间之前运行。 当它最终被重新安排时,它将会回到一个完整的满量程 ,但是不会“屈服”剩下的任何剩余量。 这种行为与睡眠线程一般丢失1个量子值的非零睡眠(实际上是10或15ms的三分之一滴答)有些不同。在Java 6中,这种行为已被改变。 Hotspot VM现在使用Windows
SwitchToThread()
API调用实现Thread.yield()
。 这个调用使得当前的线程放弃了它当前的时间片 ,而不是它的全部量子。 这意味着取决于其他线程的优先级,可以在稍后的一个中断周期中调度产生线程。 (有关时间片的更多信息,请参阅线程安排一节。)Linux的
在Linux下,Hotspot只需调用
sched_yield()
。 这个调用的结果有点不同,可能比在Windows下更严重:
- 在所有其他线程都拥有一片CPU的情况下 ,一个已排队的线程将不会得到另一个CPU 的片段 ;
- (至less在内核2.6.8以上),线程已经产生的事实被调度器的启发式对其最近的CPU分配隐式地考虑在内 – 因此,隐含地,当调度时,已经产生的线程可以被给予更多的CPU未来。
(有关优先级和调度algorithm的更多详细信息,请参见线程调度一节。)
何时使用
yield()
?我几乎从不说。 它的行为没有标准的定义,通常有更好的方法来执行你可能想用yield()来执行的任务:
- 如果您只想使用CPU的一部分,则可以通过估计线程在最后一个处理块中使用了多lessCPU,然后在一段时间内进行hibernate以进行补偿,从而以更可控的方式执行此操作:请参阅sleep()方法;
- 如果您正在等待进程或资源完成或变为可用,则有更高效的方法来完成此操作,例如通过使用join()等待另一个线程完成,使用wait / notify机制来允许一个线程向另一个人表明任务已完成,或者理想地通过使用诸如信号量或阻塞队列之类的Java 5并发结构之一。
我看到这个问题已经被一个赏金重新激活,现在问什么是yield
的实际用途。 我将以我的经验为例。
正如我们所知, yield
强制调用线程放弃正在运行的处理器,以便另一个线程可以被调度运行。 当前线程现在完成工作但是想要快速返回到队列的前端并检查某些条件是否已经改变时,这很有用。 这与条件variables有什么不同? yield
可以让线程更快地返回到运行状态。 当等待一个条件variables时,线程被挂起,需要等待另一个线程发出信号,表示应该继续。 yield
基本上是说“允许一个不同的线程运行,但是让我很快恢复工作,因为我期望我的状态能够很快地改变”。 这意味着繁忙的纺纱,一个条件可以迅速改变,但暂停线程将产生大的性能影响。
但是,喋喋不休,这里有一个具体的例子:波前平行模式。 这个问题的一个基本的例子是计算在1和2中填充的二维数组中的单个“岛”。 “岛”是一组垂直或水平相邻的细胞,
1 0 0 0 1 1 0 0 0 0 0 1 0 0 1 1 0 0 1 1
在这里,我们有两个1的岛屿:左上angular和右下angular。
一个简单的解决scheme是在整个数组上进行第一遍,并用一个递增计数器replace1个值,以至于每个1被序列号replace为主要的顺序:
1 0 0 0 2 3 0 0 0 0 0 4 0 0 5 6 0 0 7 8
在下一步中,每个值都被其本身和其邻居的值之间的最小值所替代:
1 0 0 0 1 1 0 0 0 0 0 4 0 0 4 4 0 0 4 4
现在我们可以轻易地确定我们有两个岛屿。
我们想要平行运行的部分是计算最小值的步骤。 没有太多的细节,每个线程都以交错的方式获取行,并依赖于处理上述行的线程所计算的值。 因此,每个线程需要稍微滞后于处理前一行的线程,但也必须在合理的时间内保持。 本文档中我自己介绍了更多细节和实现。 请注意sleep(0)
的使用, sleep(0)
等于yield
的C当量。
在这种情况下,使用yield
来强制每个线程暂停,但由于处理相邻行的线程在此期间会很快地前进,所以条件variables将是一个灾难性的select。
正如你所看到的, yield
是一个相当细致的优化。 在错误的地方使用它,比如在很less变化的情况下等待,会导致CPU的过度使用。
对不起,我喋喋不休地说,希望我明白了。
关于yield()
, interrupt()
和join()
之间的区别 – 一般来说,不仅仅是在Java中:
- 屈服 :从字面上看,“屈服”意味着放弃,放弃,投降。 一个良好的线程告诉操作系统(或虚拟机,或不),它愿意让其他线程安排在其中。 这表明它没有做太重要的事情。 这只是一个提示,但不保证有任何效果。
- join :当多个线程在某个句柄,或者令牌或者实体上“join”时,所有这些线程都会一直等到所有其他相关线程完成执行(完全或者达到他们自己的对应连接)。 这意味着一堆线程都完成了他们的任务。 然后,可以安排这些线程中的每一个继续其他工作,能够假设所有这些任务确实完成。 (不要与SQLjoin混淆!)
- 中断 :由一个线程用来“戳”另一个正在hibernate,等待或join的线程,以便计划继续再次运行,可能是指示它已被中断。 (不要与硬件中断混淆!)
对于Java专门,请参阅
-
加盟:
如何使用Thread.join? (这里在StackOverflow)
何时join线程?
-
产量:
-
中断:
是Thread.interrupt()邪恶? (这里在StackOverflow)
首先,实际的描述是
使当前正在执行的线程对象暂时暂停并允许其他线程执行。
现在,在执行新线程的run
方法之前,主线程很可能会执行五次循环,所以只有在主线程中的循环执行之后,所有的yield
调用才会发生。
join
将停止当前的线程,直到正在使用join()
调用的线程执行完毕。
interrupt
会中断正在调用的线程,导致InterruptedException 。
yield
允许上下文切换到其他线程,所以这个线程不会占用整个进程的CPU使用量。
事实上,yield()的主要用途是什么?
良率build议CPU可以停止当前线程并开始执行具有更高优先级的线程。 换句话说,为当前线程分配一个低优先级的值,为更重要的线程留出空间。
我相信下面的代码在使用yield()和不使用yield时会产生相同的输出。 它是否正确?
不,这两个会产生不同的结果。 如果没有yield(),一旦线程得到控制,它将一次执行“Inside run”循环。 但是,对于yield(),一旦线程得到控制,它将打印一次“内部运行”,然后将控制交给其他线程(如果有的话)。 如果没有挂起的线程,这个线程将被重新开始。 所以每次执行“Inside run”时,都会寻找其他线程来执行,如果没有线程可用,当前线程将继续执行。
yield()与join()和interrupt()方法有什么不同?
yield()是给其他重要线程的空间,join()是等待另一个线程完成其执行,而interrupt()是用于中断当前正在执行的线程来做其他事情。
Thread.yield()
使线程从“正在运行”状态变为“可运行”状态。 注意:它不会导致线程进入“等待”状态。
1.在波纹pipe码中,使用屈服方法可以得到相同的输出。 这是对的吗?
在这种情况下没有指定正确的输出,所以任何东西都是正确的。
2. yield()的主要用途是什么?
它几乎没有用过,更不用说足以确定一个“主要用途”。 我从来没有在任何平台上使用yield()方法,而且我已经将它们提供给了我超过20年,而且我在整个时期都进行了非常严格的系统编程。
3.如何与join()和interrupt()方法不同?
这是不一样的,它是不一样的。 这个问题完全没有意义。
Thread.yield()
调用Thread.yield()方法时,线程调度程序将当前正在运行的线程保持为Runnable状态,并select另一个同等优先级或更高优先级的线程。 如果没有相等和更高优先级的线程,则重新调度调用yield()线程。 记住yield方法不会使线程进入等待或阻塞状态。 它只能使一个线程从运行状态变为运行状态。
join()
当一个线程实例调用join时,这个线程会告诉当前正在执行的线程等待Join线程完成。 Join用于当前任务完成前应完成的任务。
yield()主要用于搁置multithreading应用程序。
所有这些方法的不同之处在于yield()在执行另一个线程时放置线程并在该线程完成后返回,join()会将线程的开始一起执行直到结束,并且在该线程之后运行另一个线程结束,interrupt()会停止执行一段时间的线程。