Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.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_Multithreading_Thread Safety - Fatal编程技术网

Java 仅当更新操作不是';我还没跑呢

Java 仅当更新操作不是';我还没跑呢,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我需要在收到通知时异步执行更新操作。下面的update()方法操作实例变量 public class UpdateOperation implements Runnable { private Boolean isInProgress = false; @Override public void run() { try { synchronized

我需要在收到通知时异步执行更新操作。下面的
update()
方法操作实例变量

    public class UpdateOperation implements Runnable
    {
        private Boolean isInProgress = false;

        @Override
        public void run() {
            try 
            {
                synchronized (isInProgress)
                {
                    isInProgress = true;
                }
                update(); //perform update
                synchronized (isInProgress)
                {
                    isInProgress = false;
                }
            } 
            catch (UpdaterException e) 
            {
                    // deal with it                 
            }
        }

    }

// In another class
private UpdateOperation mCurrentUpdateOperation = new UpdateOperation(); 

public void updateRequired()
{
    synchronized (mCurrentUpdateOperation.isInProgress)
    {
        if (!mCurrentUpdateOperation.isInProgress)
        {
            new Thread(mCurrentUpdateOperation).start();
        }
        else
        {
            // reschedule or silently ignore                
        }
    }   
}
此设置是否足以使两(2)个更新操作同时运行?我相信这是因为到达
synchronized
块的第一个线程将获取锁,启动操作并释放锁。然后第二个(或更多个)将获取锁,查看操作正在进行,重新调度,然后释放锁

这个设置会失败吗

此设置是否足以使两(2)个更新操作同时运行

否,因为您正在锁定的对象。您应该始终在非最终对象上同步,而不要在
布尔值上同步。当
isInProgress
的值更改时(当它设置为
true
false
时),多个线程将锁定不同的对象,并且可以同时进入互斥块

如果可以将
UpdateOperation
实例设置为final,则可以锁定该实例。您可以随时执行以下操作:

 private final Object lockObject = new Object();
 ...
 synchronized (lockObject) {
     ...
 }
锁定对象后,可以检查进程中的
状态,该状态可能是布尔基元。
synchronize
构造同步所有内存。有关更多信息,请参阅

锁定
Boolean
非常糟糕,因为在整个JVM中只有两个常量对象引用(除非您执行
new Boolean(…)
)。当你说:

isInProgress = true;
你实际上是在说:

isInProgress = Boolean.TRUE;
所以所有类中的所有线程都将锁定在相同的2个对象上,结果很奇怪

有关更多信息,请参见我的回答:

此设置是否足以使两(2)个更新操作同时运行

否,因为您正在锁定的对象。您应该始终在非最终对象上同步,而不要在
布尔值上同步。当
isInProgress
的值更改时(当它设置为
true
false
时),多个线程将锁定不同的对象,并且可以同时进入互斥块

如果可以将
UpdateOperation
实例设置为final,则可以锁定该实例。您可以随时执行以下操作:

 private final Object lockObject = new Object();
 ...
 synchronized (lockObject) {
     ...
 }
锁定对象后,可以检查进程中的
状态,该状态可能是布尔基元。
synchronize
构造同步所有内存。有关更多信息,请参阅

锁定
Boolean
非常糟糕,因为在整个JVM中只有两个常量对象引用(除非您执行
new Boolean(…)
)。当你说:

isInProgress = true;
你实际上是在说:

isInProgress = Boolean.TRUE;
所以所有类中的所有线程都将锁定在相同的2个对象上,结果很奇怪

有关更多信息,请参见我的回答:

看看s。它们将提供一个线程池,您只需添加runnable即可。此外,您可能希望使用AtomicInteger

我认为这将为您提供您想要的一切,更易于使用。

看看s。它们将提供一个线程池,您只需添加runnable即可。此外,您可能希望使用AtomicInteger


我认为这将为您提供您想要的一切,更易于使用。

原始解决方案的另一个问题是检查和设置
isInProgress
变量位于不同的同步语句中,这会产生时间间隔。因此,可以启动多个线程

正确的解决方案是:

public class UpdateOperation implements Runnable {
    private boolean inProgress = false;

    public void start() {
       synchronized (this) {
           if (inProgress) {
              return;
           }
           inProgress=true;
       }
       new Thread(this).start();
    }

    @Override
    public void run() {
        try  {
            update(); //perform update
        } catch (UpdaterException e) {
                // deal with it                 
        } finally {
            synchronized (this) {
                inProgress = false;
            }
        }
    }

}

// In another class
private UpdateOperation mCurrentUpdateOperation = new UpdateOperation(); 

public void updateRequired() {
      mCurrentUpdateOperation.start();
}

原始解决方案的另一个问题是,在不同的同步语句中检查和设置
isInProgress
变量,这会产生时间间隔。因此,可以启动多个线程

正确的解决方案是:

public class UpdateOperation implements Runnable {
    private boolean inProgress = false;

    public void start() {
       synchronized (this) {
           if (inProgress) {
              return;
           }
           inProgress=true;
       }
       new Thread(this).start();
    }

    @Override
    public void run() {
        try  {
            update(); //perform update
        } catch (UpdaterException e) {
                // deal with it                 
        } finally {
            synchronized (this) {
                inProgress = false;
            }
        }
    }

}

// In another class
private UpdateOperation mCurrentUpdateOperation = new UpdateOperation(); 

public void updateRequired() {
      mCurrentUpdateOperation.start();
}

(+1)说得再好不过了。使用
对象
锁,我如何检查操作的状态?您先锁定对象,然后在进程中检查
的状态
@SotiriosDelimanolis
synchronize
同步所有内存,因此如果您愿意,inProgress可以是一个基本布尔值。请看这里:我不能只锁定我的
UpdateOperation
对象而不是一个新对象。如果它从未更改,您可以。如果它是
最终的
,那么@SotiriosDelimanolis(+1)说得再好不过了。对于
对象
锁定,我如何检查操作的状态?您锁定对象,然后检查
inProgress
@SotiriosDelimanolis的状态
synchronize
同步所有内存,因此如果您愿意,inProgress可以是一个基本布尔值。请看这里:我不能只锁定我的
UpdateOperation
对象而不是一个新对象。如果它从未更改,您可以。如果是
final
则是@SotiriosDelimanolis。使用执行器无助于解决任务。从任务的角度来看,如果UpdateOperation在执行器或单独的线程上运行,则没有区别。SingleThreadExecutor将为您的可运行线程排队。因此,每次只有一个操作。当更新已经运行时,OP希望“重新安排或静默忽略”。对于执行器,您可以重新安排后续操作(将其放入队列并在之后执行),但您无法获得“静默忽略”行为。使用执行器无助于解决任务。从任务的角度来看,如果UpdateOperation在执行器或单独的线程上运行,则没有区别。SingleThreadExecutor将为您的可运行线程排队。因此,每次只有一个操作。当更新已经运行时,OP希望“重新安排或静默忽略”。有了执行器,您可以重新安排后续操作(它被放入队列并在之后执行),但您无法获得“静默忽略”行为。