将无状态回调放入 BlockingQueue 是否安全?
Is it safe to put a stateless callback into BlockingQueue?
我有以下非常简单的回调接口和一个 POJO class:
public interface Action{
public void doAction();
}
public class Person{
private String name;
private String address;
//...etc
//GET, SET, toString
}
我将按如下方式使用它:
public class ActionExecutor{
private static final Logger logger = LogManager.getLogger(ActionExecutor.class);
private final BlockingQueue<Action> blockingQueue = new LinkedBlockingQueue(2000);
public void execute(final Person p){
//modify state of p in some way
blockingQueue.put(new Action(){
public void doAction(){
logger.info("Execution started: " +p.toString );
//do some other job
});
}
}
BlockingQueue
这里用来实现producer-consumer
问题: 是否保证从 BlockingQueue
执行操作的消费者线程会写入正确的日志消息? IE。它观察到 Person
的正确状态?但我对此不是很确定。
我认为不,这不能保证,因为在生产者修改和生产者读取之间的订单之前没有发生任何事情。
答案是视情况而定。
如果在那之后你从未修改过Person实例,那么它是有保证的。正如 in the docs:
所述,存在先行关系
Memory consistency effects: As with other concurrent collections,
actions in a thread prior to placing an object into a BlockingQueue
happen-before actions subsequent to the access or removal of that
element from the BlockingQueue in another thread.
但是,我还是不会那样做。如果在 回调被放入队列后修改了 Person 实例,then 没有任何保证。您可以说记录器保证打印至少与添加到队列时一样最新的状态。
因此消费者将看到这些修改:
public void execute(final Person p){
//modify state of p in some way
blockingQueue.put(new Action(){
但不是在那之后制作的那些。而且由于在将 p
传递给 new Action()
对象后你保留了它,所以我会避免这种情况。相反,我会做这样的事情:
public void execute(final Person p){
//modify state of p in some way
blockingQueue.put(new Action() {
final String executionName = p.toString();
public void doAction(){
logger.info("Execution started: " + executionName);
//do some other job
});
}
现在状态被捕获在最终变量中。消费者将看到该值,无论当时 p
的状态如何。
我有以下非常简单的回调接口和一个 POJO class:
public interface Action{
public void doAction();
}
public class Person{
private String name;
private String address;
//...etc
//GET, SET, toString
}
我将按如下方式使用它:
public class ActionExecutor{
private static final Logger logger = LogManager.getLogger(ActionExecutor.class);
private final BlockingQueue<Action> blockingQueue = new LinkedBlockingQueue(2000);
public void execute(final Person p){
//modify state of p in some way
blockingQueue.put(new Action(){
public void doAction(){
logger.info("Execution started: " +p.toString );
//do some other job
});
}
}
BlockingQueue
这里用来实现producer-consumer
问题: 是否保证从 BlockingQueue
执行操作的消费者线程会写入正确的日志消息? IE。它观察到 Person
的正确状态?但我对此不是很确定。
我认为不,这不能保证,因为在生产者修改和生产者读取之间的订单之前没有发生任何事情。
答案是视情况而定。
如果在那之后你从未修改过Person实例,那么它是有保证的。正如 in the docs:
所述,存在先行关系Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a BlockingQueue happen-before actions subsequent to the access or removal of that element from the BlockingQueue in another thread.
但是,我还是不会那样做。如果在 回调被放入队列后修改了 Person 实例,then 没有任何保证。您可以说记录器保证打印至少与添加到队列时一样最新的状态。
因此消费者将看到这些修改:
public void execute(final Person p){
//modify state of p in some way
blockingQueue.put(new Action(){
但不是在那之后制作的那些。而且由于在将 p
传递给 new Action()
对象后你保留了它,所以我会避免这种情况。相反,我会做这样的事情:
public void execute(final Person p){
//modify state of p in some way
blockingQueue.put(new Action() {
final String executionName = p.toString();
public void doAction(){
logger.info("Execution started: " + executionName);
//do some other job
});
}
现在状态被捕获在最终变量中。消费者将看到该值,无论当时 p
的状态如何。