gpt4 book ai didi

java - 一次仅由一个线程使用一个对象

转载 作者:行者123 更新时间:2023-12-03 13:23:21 25 4
gpt4 key购买 nike

我有一个集合(Map )。在多线程环境中,我需要map中的myObject实例一次只能由一个线程使用。考虑下面的例子。

public class MyObject{

String name;
public MyObject(String objName){
this.name = name;
}
public void doSomeTimeConsumingAction(){
Thread.sleep(10000);
}
public void doSomeOther(){
//doSomething
}
public void doMany(){
//doSomething
}
}

public class ObjectUtil {

public static Map<String, MyObject> map = new HashMap<>();
static {
map.put("a", new MyObject("a"));
map.put("b", new MyObject("b"));
map.put("c", new MyObject("c"));
}

public static getObject(String key){
return map.get(key);
}

}

public static void main(String[] args){

Thread t1 = new Thread(new Runnable(){
@Override
public void run(){
System.out.println("t1 starts");
MyObject obj = ObjectUtil.getObject("a");
obj.doSomeTimeConsumingAction();
System.out.println("t1 ends");
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run(){
System.out.println("t2 starts");
MyObject obj = ObjectUtil.getObject("a");
obj.doSomeTimeConsumingAction();
System.out.println("t2 ends");
});
Thread t3 = new Thread(new Runnable(){
@Override
public void run(){
System.out.println("t3 starts");
MyObject obj = ObjectUtil.getObject("b");
obj.doSomeTimeConsumingAction();
System.out.println("t3 ends");
});

t1.start();
t2.start();
t3.start();
}
我的预期输出
t1 starts
t2 starts
t3 starts
/* wait 10 sec */
t1 ends
t3 ends
/* wait 10 sec */
t2 ends
解释->在上面,线程t1和t2都尝试使用键“a”访问映射中的同一实例,而t3使用键“b”访问不同的实例。因此,t1,t2,t3同时启动。 t1,t3(或t2,t3)先结束,然后另一个结束。
我无法在map或getObject()方法上使用同步,因为不会锁定要使用的对象实例。
简而言之,我怎么知道线程是否使用对象的实例?并且,如何防止其他线程访问同一实例?是否有可能?
编辑:更新了代码,我也无法同步对象中的doSomeTimeConsumingAction方法,因为其他线程可能会访问该方法,这与要访问的方法无关,整个实例只能由一个线程访问一个时间。请问我问的太多了。

最佳答案

除非您知道每个调用方都只会调用一个方法,否则同步所有方法是不可行的。否则,调用可能会交错,这通常是个坏主意。如有疑问,调用者应在处理整个实例之前对其进行同步。
如果您不信任所有调用者都遵循该规则-这是“锁定” MyObject的一种简单方法。

    public static Map<String, MyObject> map = new ConcurrentHashMap<>();

public static void handle(String key, Consumer<MyObject> handle) {
map.computeIfPresent(key, o -> {
handler.apply(o); // Only one thread can be here at a time for any given "o"
return o;
});
}
...
ObjectUtil.handle("a", o -> o.doSomeTimeConsumingAction());
尽管简短安全,但这并不是最大的线程性能(CHM可能还会阻止对其他 MyObject的访问)。

关于java - 一次仅由一个线程使用一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63563067/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com