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