div*_*ivz 98 java multithreading yield-keyword concurrent-programming
我yield()对Java 中方法的使用有点困惑,特别是在下面的示例代码中.我还读过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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用和不使用上面的代码我获得相同的输出yield():
Inside main
Inside main
Inside main
Inside main
Inside main
Inside run
Inside run
Inside run
Inside run
Inside run
Run Code Online (Sandbox Code Playgroud)
Sat*_*ick 93
资料来源: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或15毫秒的1/3).在Java 6中,此行为已更改.Hotspot VM现在
Thread.yield()使用WindowsSwitchToThread()API调用实现.这个调用使当前线程放弃其当前时间片,但不是它的整个量子.这意味着根据其他线程的优先级,可以在稍后的一个中断周期中调度退出线程.(有关时间片的更多信息,请参阅有关线程调度的部分.)Linux的
在Linux下,Hotspot只是调用
sched_yield().此调用的后果有点不同,可能比Windows更严重:
- 在所有其他线程都有一片CPU 之前,一个屈服的线程不会得到另一片CPU ;
- (至少在内核2.6.8以后),调度程序对其最近的CPU分配的启发式隐含地考虑了线程已经产生的事实 - 因此,隐含地,已经产生的线程可以在调度时给予更多的CPU.未来.
(有关优先级和调度算法的更多详细信息,请参阅有关线程调度的部分.)
什么时候用
yield()?我几乎从不说.它的行为没有标准定义,并且通常有更好的方法来执行您可能想要使用yield()执行的任务:
- 如果您只是尝试使用CPU的一部分,可以通过估计线程在其最后一块处理中使用了多少CPU,然后睡眠一段时间来补偿,以更可控的方式执行此操作:请参阅的睡眠()方法;
- 如果你正在等待一个进程或资源完成或变得可用,有更有效的方法来实现这一点,例如通过使用join()等待另一个线程完成,使用wait/notify机制允许一个线程向另一个人发出任务完成的信号,或理想情况下使用Java 5并发结构之一,如信号量或阻塞队列.
Tud*_*dor 37
我看到这个问题已经通过赏金重新激活,现在询问实际用途yield是什么.我将从我的经验中给出一个例子.
正如我们所知,yield强制调用线程放弃它的运行上,以便其他线程可以被调度运行的处理器.当前线程现在已完成其工作但希望快速返回队列前端并检查某些条件是否已更改时,这非常有用.这与条件变量有什么不同?yield使线程能够更快地返回到运行状态.在等待条件变量时,线程被挂起,需要等待另一个线程发出信号表明它应该继续.yield基本上说"允许一个不同的线程运行,但允许我很快恢复工作,因为我希望在我的状态很快就会发生变化".这暗示了忙碌的旋转,其中条件可以快速改变但是暂停线程将导致大的性能损失.
但足够的bab呀学语,这是一个具体的例子:波前平行模式.该问题的基本实例是在填充0和1的二维数组中计算1的单个"岛"."孤岛"是一组垂直或水平相邻的单元:
1 0 0 0
1 1 0 0
0 0 0 1
0 0 1 1
0 0 1 1
Run Code Online (Sandbox Code Playgroud)
这里我们有两个1s岛:左上角和右下角.
一个简单的解决方案是对整个数组进行第一次传递,并用递增计数器替换1个值,以便最后每个1用行主序中的序列号替换:
1 0 0 0
2 3 0 0
0 0 0 4
0 0 5 6
0 0 7 8
Run Code Online (Sandbox Code Playgroud)
在下一步中,每个值都由其自身与其邻居值之间的最小值替换:
1 0 0 0
1 1 0 0
0 0 0 4
0 0 4 4
0 0 4 4
Run Code Online (Sandbox Code Playgroud)
我们现在可以轻松确定我们有两个岛屿.
我们想要并行运行的部分是我们计算最小值的步骤.在不进行太多细节的情况下,每个线程以交错的方式获取行,并依赖于处理上面行的线程计算的值.因此,每个线程需要稍微滞后于处理前一行的线程,但也必须在合理的时间内保持.我自己在本文档中介绍了更多细节和实现.注意其用法sleep(0)或多或少是C的等价物yield.
在这种情况下yield,使用的是为了强制每个线程依次暂停,但由于处理相邻行的线程在此期间会非常快速地前进,因此条件变量将证明是灾难性的选择.
如您所见,这yield是一个非常精细的优化.在错误的地方使用它,例如在很少变化的条件下等待,将导致CPU的过度使用.
抱歉长期唠叨,希望我清楚自己.
ein*_*ica 12
关于之间的差异yield(),interrupt()以及join()-在一般情况下,不只是在Java中:
具体来说,请参阅
加盟:
如何使用Thread.join?(这里是StackOverflow)
产量:
中断:
Thread.interrupt()是邪恶的吗?(这里是StackOverflow)
首先,实际描述是
导致当前正在执行的线程对象暂时暂停并允许其他线程执行.
现在,您的主线程很可能在执行run新线程的方法之前执行循环五次,因此所有调用yield仅在主线程中的循环执行后才会发生.
join将停止当前线程,直到被调用的线程join()完成执行.
interrupt将中断正在调用它的线程,导致InterruptedException.
yield 允许上下文切换到其他线程,因此该线程不会消耗进程的整个CPU使用率.
| 归档时间: |
|
| 查看次数: |
95824 次 |
| 最近记录: |