我有一个正忙的旋转等待循环,等待设置一个标志。然而,要做到这一点需要花费大量的时间--分钟,甚至几个小时。
发布于 2018-07-07 13:02:19
那么,您想看一个关于Object及其长期可用的wait()和notify/All()方法的简短示例吗?(他们已经是那里 in JLS 1.0,从20+几年前开始)
别再说了:
public class NotifyTest {
private boolean flag = false;
public synchronized boolean getFlag() {
return flag;
}
public synchronized void setFlag(boolean newFlag) {
flag = newFlag;
notifyAll();
}
public static void main(String[] args) throws Exception {
final NotifyTest test = new NotifyTest();
new Thread(new Runnable() {
@Override
public void run() {
System.out.printf("I am thread at %,d, flag is %b\n",
System.currentTimeMillis(), test.getFlag());
synchronized (test) {
try {
test.wait();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
System.out.printf("I am thread at %,d, flag is %b\n",
System.currentTimeMillis(), test.getFlag());
}
}).start();
System.out.printf("I am main at %,d, flag is %b\n",
System.currentTimeMillis(), test.getFlag());
Thread.sleep(2000);
test.setFlag(true);
System.out.printf("I am main at %,d, flag is %b\n",
System.currentTimeMillis(), test.getFlag());
}
}如果您的等待循环还有其他工作要做,Object.wait()也有带有超时的变体。
因此,对象可以是wait()-ed on,然后可以通知等待线程(其中一个通过notify(),或者所有等待线程都通过notifyAll()),它们甚至不需要相互了解。
由于等待和通知都必须发生在同步块中,所以启动块、检查变量/标志/任何东西并有条件地发出等待都是安全和可能的(这里没有显示这些构造)。
发布于 2018-07-06 17:45:21
来自文档 of Thread#onSpinWait
运行时可以采取行动,以提高调用自旋等待循环结构的性能。
Thread#sleep没有这样做,而是将处理器释放到另一个可运行的线程,直到其休眠时间过去。
如果我是您,我会重新设计您的系统,使用中断(事件)而不是轮询(忙着等待),因为这样会比Thread#sleep或Thread#onSpinWait更好地提高性能。
发布于 2018-07-06 17:51:12
在这种情况下,睡眠和旋转锁都不是你想要的。睡眠是错误的选择,因为你不知道你需要提前多长时间睡觉。执行某种类型的自旋锁循环是错误的,因为自旋锁是繁忙的等待,因此消耗CPU周期,并且只用于非常短的等待,因为预计资源会很快可用。你在这里要做的是设置一个信号量。让线程1等待线程2设置信号量。
https://stackoverflow.com/questions/51215310
复制相似问题