Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 - Fatal编程技术网

如何在Java中基于条件同步代码

如何在Java中基于条件同步代码,java,multithreading,Java,Multithreading,我们有以下代码要在Java中执行: public void doSomething() { doSomeDBOperationForOrg(); doOtherOperations(); } void doSomeDBOperationForOrg() { //should be executed only once per organization. } void doOtherOperations() { //should be executed onl

我们有以下代码要在Java中执行:

public void doSomething() {
    doSomeDBOperationForOrg();
    doOtherOperations();
}

void doSomeDBOperationForOrg() { 
    //should be executed only once per organization.
}

void doOtherOperations() {
    //should be executed only when the DB operation for the organization is done, and not before
}
多个组织下的多个用户同时调用方法
doSomething
。每个组织只需要执行一次方法
doSomeDBOperationForOrg
,并且对调用
doSomething
方法的所有用户执行
doOtherOperations
,但只有在
doSomeDBOperationForOrg
完成之后

一种选择是通过
doSomething
和/或
doSomeDBOperationForOrg
进行“同步”,并维护更新组织的列表

public synchronized void doSomething() {
    if(!orgUpdatedList.contains(organization)) {
        doSomeDBOperationForOrg();
        orgUpdatedList.add(organization);
    }
    
    doOtherOperations();
}
但这将阻止所有用户的线程,而不管他们的组织如何。这是不可取的,当我们有一个庞大的用户名单。
有人能建议一种更好的方法来实现这一点吗?

您想执行
doOtherOperations()自由并行,因此这不应在任何(有效)
同步
块中

但是您需要
doSomeDBOperationForOrg()每个组织发生一次。当您处理多个线程时,像“每xyz一次”这样的需求需要某种类型的同步

您不希望用户等待他们不属于的组织的初始化

建议:

如果您有一个类(我们称之为
Organization
)代表组织(从某种意义上说,一个组织被1:1映射到一个实例,同一组织没有重复的实例),那么您可以使
doSomeDBOperationForOrg()
组织
类的同步实例方法,并让此方法检查是否需要初始化。那么
doSomething()
就相当简单了:

public void doSomething() {
    organization.doSomeDBOperationForOrg();
    doOtherOperations();
}
或者,更接近您当前的结构:

public void doSomething() {
    synchronized (organization) {
        if(!orgUpdatedList.contains(organization)) {
            doSomeDBOperationForOrg();
            orgUpdatedList.add(organization);
        }
    }
    doOtherOperations();
}
但请确保使用线程安全的
orgUpdatedList
,例如,通过将
Collections.synchronizedXyz()
包装在其周围

通过在组织上进行同步,可以确保来自一个组织的用户可以相互阻止,这样可以有序地初始化,但不会受到来自其他组织的用户的影响

如果您没有适当的
组织
类(并且无法引入),而只有
字符串
,则可以在
组织.intern()上进行同步。该方法的属性是,具有相同内容的所有字符串都会产生相同的实例。这是一种黑客行为,但应该有效