如何在Java中基于条件同步代码
我们有以下代码要在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
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()上进行同步。该方法的属性是,具有相同内容的所有字符串都会产生相同的实例。这是一种黑客行为,但应该有效