- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我写了一个简单的应用程序,它有主线程(生产者)和多个消费者线程。我想从主线程广播一条消息,所以所有的消费者线程都会收到它。但是,我有麻烦。我试图了解如何 Thread.sleep可能与 Happens-Before 有关.这是我的一段代码:
import java.util.*;
public class PubSub {
public static void main(String[] args) {
List<Consumer> consumers = new ArrayList<>();
for (int i = 0; i < 3; i++ ) {
Consumer consumer = new Consumer(
"Consumer" + i
);
consumer.start();
consumers.add(consumer);
}
Scanner scanner = new Scanner(System.in);
while(true) {
String message = scanner.nextLine();
for (Consumer consumer: consumers) {
consumer.notify(message);
}
}
}
static class Consumer extends Thread {
private Queue<String> queue;
public Consumer(String name) {
super(name);
this.queue = new LinkedList<>();
}
@Override
public void run() {
while(true) {
if (!queue.isEmpty()) {
String message = queue.poll();
System.out.println(
getName() + ": Consuming message: " + message
);
}
}
}
public void notify(String message) {
queue.add(message);
}
}
}
如果我添加 sleep ,消费者将开始接收消息:
@Override
public void run() {
while(true) {
try {
Thread.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!queue.isEmpty()) {
String message = queue.poll();
System.out.println(
getName() + ": Consuming message: " + message
);
}
}
}
由于 Thread.sleep 是一个本地方法,我想了解它是如何解析 happens-before 的。
我必须指出,修复发生前的真正方法是制作 volatile 关键字:
private volatile Queue<String> queue;
如果您将同步 添加到队列,它也会解决问题:
@Override
public void run() {
synchronized (queue) {
while (true) {
if (!queue.isEmpty()) {
String message = queue.poll();
System.out.println(
getName() + ": Consuming message: " + message
);
}
}
}
}
最佳答案
I'm trying to understand how Thread.sleep may be related to Happens-Before
happens-before 和 Thread.sleep
之间没有关系。 JLS明确指定 Thread.sleep
没有任何同步语法:
Neither a sleep for a period of zero time nor a yield operation need have observable effects. It is important to note that neither Thread.sleep nor Thread.yield have any synchronization semantics. In particular, the compiler does not have to flush writes cached in registers out to shared memory before a call to sleep or yield, nor does the compiler have to reload values cached in registers after a call to sleep or yield. For example, in the following (broken) code fragment, assume that this.done is a non-volatile boolean field:
while (!this.done)
Thread.sleep(1000);The compiler is free to read the field this.done just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if another thread changed the value of this.done
在相关说明中,如果在 while
循环之后添加在运行时评估的语句,消费者似乎开始消费消息(在我的机器上)。例如,添加 this.toString()
会导致消费者开始消费消息。
public void run() {
while(true) {
this.toString();
这仍然不能解释该行为,但它进一步证实 Thread.sleep
不一定是 Consumer
突然看到队列更新的原因。
关于java - Thread.sleep 和 happens-before 有什么关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42417636/
我们有一些第三方代码,它们执行以下操作 列表项 创建用户交易,例如 txn = (UserTransaction)ctx.lookup( "UserTransaction" ); txn.begi
表达式 "a".(strlen('ab')-strlen('a')) 按预期计算为 a1。 但是如果我不小心省略了括号, "a".strlen('ab')-strlen('a') 计算结果为-1。这里
我读到了有关 Java 类型删除的内容 on Oracle's website . 什么时候发生类型删除?在编译时还是运行时?类什么时候加载?类何时实例化? 很多网站(包括上面提到的官方教程)都说
我读到了有关 Java 类型删除的内容 on Oracle's website . 什么时候发生类型删除?在编译时还是运行时?类什么时候加载?类何时实例化? 很多网站(包括上面提到的官方教程)都说
我试图对 Haskell 中类型族“发生”的类型级计算何时(以及多少次)形成一种直觉。对于一个具体的例子,考虑这个类型类来索引到 n-ary product使用类型级自然: {-# LANGUAGE
我正在阅读 Java Concurrency in Practice书。 在阅读关于 JMM 的章节时,它说: The JMM defines a partial ordering called ha
我读到了 Java 的类型删除 on Oracle's website . 类型删除何时发生?在编译时还是运行时?什么时候加载类?什么时候实例化类? 很多网站(包括上面提到的官方教程)都说类型删除发生
我一周前通过互联网向 Apple 申请加入 Iphone 开发计划,并向他们发送了我的 99.00 美元。 我的印象是,总的来说,响应速度很快。然而,除了一封确认我购买的电子邮件之外,我什么也没看到。
我读到了 Java 的类型删除 on Oracle's website . 什么时候发生类型删除? 在编译时还是运行时?什么时候加载类?什么时候实例化类? 很多网站(包括上面提到的官方教程)都说类型删
我读到了 Java 的类型删除 on Oracle's website . 类型删除何时发生?在编译时还是运行时?什么时候加载类?什么时候实例化类? 很多网站(包括上面提到的官方教程)都说类型删除发生
有一个快速同步问题,这是我的: a) Class1 的并发 HashMap 定义如下: ConcurrentMap map = new ConcurrentHashMap(); b) Class2
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我正在研究 Java 并发性并找到了以下资源以供引用, http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-su
我根据Douglas Crockford在他的书“Javascript: the good parts”中提出的布局创建了一个对象构造函数。 此构造函数在添加各种成员和方法后返回一个 that 对象。
我正在编写一个单元测试(在 Mocha 中使用 Chai)来查看某个对象 o 是否是 instanceof ClassY。单元测试成功,但我可以让它失败,具体取决于我如何创建对象文字,尽管生成的对象文
假设我有一个包装 HashMap 的类,如下所示: public final class MyClass{ private final Map map; //Called by T
我想弄清楚 happens-before 属性的确切含义。 我看到 happens-before 属性的解释说,如果全局变量(不是易变的或包含在同步块(synchronized block)中)的更新
虽然在 SO 和其他地方有很多关于 happens-before 关系的帖子,但我很难找到我的问题的明确答案。 考虑两个 Java 线程: 最初,flag == false 和 data == 0 T
http://coliru.stacked-crooked.com/a/c795a5d2bb91ae32 #include struct X { X(const char *) { std:
我读到了 Java 的类型删除 on Oracle's website . 类型删除何时发生?在编译时还是运行时?什么时候加载类?什么时候实例化类? 很多网站(包括上面提到的官方教程)都说类型删除发生
我是一名优秀的程序员,十分优秀!