Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何确保一个代码块在多线程环境中只执行一次?_Java_Thread Safety_Akka - Fatal编程技术网

Java 如何确保一个代码块在多线程环境中只执行一次?

Java 如何确保一个代码块在多线程环境中只执行一次?,java,thread-safety,akka,Java,Thread Safety,Akka,我有一个非单例参与者正在创建一个我只想创建一次的对象。这是如何实现的?演员可以是单身吗?如果是,如何进行 class NonSingletonActor extends UntypedActor { public static onReceive(Object arg) throws Exception { *block of code that needs to be executed once!* } } 您可以在类本身上使用synchronized块,并使用

我有一个非单例参与者正在创建一个我只想创建一次的对象。这是如何实现的?演员可以是单身吗?如果是,如何进行

class NonSingletonActor extends UntypedActor {

   public static onReceive(Object arg)  throws Exception {

         *block of code that needs to be executed once!*
} }

您可以在类本身上使用synchronized块,并使用布尔标志,如:

class NonSingletonActor extends UntypedActor {

  private static volatile boolean executed;

  public static onReceive(Object arg)  throws Exception {
    if (executed)
      return;

    synchronized (NonSingletonActor.class) {
      if (executed)
        return; 

      executed= true; 
      *block of code that needs to be executed once!*
    }
  } 
}
如果您可以在代码块中获得异常,并希望能够再次执行它,那么您可以仅在成功创建对象时将标志设置为true。

an非常适合这样做,尤其是它的
compareAndSet
方法。该方法接受两个参数:“预期”值和新值。它原子地做三件事:(a)检查当前值是否等于预期值,(b)如果是,则将当前值更新为新值,(c)在发生更新时返回true(即,如果预期值和旧值相同)


此代码将检查
hasRun
是否有“false”值(这是其初始状态)。如果是这样,它将自身设置为“true”,并运行
If
的块;否则,它将保持其当前状态,并且不会运行
if
的块。关键的是,检查和设置是原子的(正如类名所暗示的),这意味着没有两个线程可以同时看到错误的值;其中一个线程将看到假值并将其设置为真,而另一个线程无法在这两个操作之间“潜入”。

这些其他答案似乎忽略了一个事实,即您的问题是在Akka参与者的上下文中提出的

如果您有一个需要从多个参与者引用但只创建一次的对象,那么您应该将这些操作委托给另一个参与者—该参与者将创建和管理相关对象,然后将引用共享给该参与者


nonsingletonator
需要对该对象进行操作时,它将向包含该对象的参与者发送一条消息。如果将Akka与此处显示的其他解决方案混合使用,我会非常犹豫,我希望您会看到一些意外的行为。

通常,您可以使用同步化的int runCount和runCountMutex;runCount的getter和incremoter使用ruNCountMutex对象,以及处理它的所有代码,例如if(runCount<1){do code}。但也许有一个明确的aka技术,我不明白,有问题的代码块不会并行执行吗?在这种情况下,计数将如何工作?你能在回答中张贴这个例子吗?见下面斯坦尼斯拉夫的回答。我会使用一个显式的自创建对象作为互斥对象,他使用了(nonsingletonator.class对象。)onReceive是一个重写的方法。这仍然可能吗?不,在这种情况下,您可以在iTunes中使用一个同步块更新我的答案,现在它使用一个块同步标志不应该是静态的吗?此外,您可以使用双重检查锁定
if(!executed){synchronized(lock){if(!executed)..
,并且主执行代码可以在sync块之外执行。if
executed
始终被访问(用于读写)在同步块内部,它不需要是易失性的;同步提供了一个“先于发生”的边缘。如果您想在同步块外部以某种双重检查锁定模式检查执行的
,则只需要将其设置为易失性的。
private static final AtomicBoolean hasRun = new AtomicBoolean(false);

...
if (hasRun.compareAndSet(false, true)) {
    // your code here
}