【发布时间】:2026-01-01 18:40:02
【问题描述】:
我有一个集合( Map
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,因为线程可以访问其他方法。这与访问方法无关,整个实例只能通过以下方式访问一次一个线程。如果问的太多,请见谅。
【问题讨论】:
-
可以同步
doSomeTimeConsumingOperation。 -
@BurakSerdar 我不能这样做,因为我需要使用整个对象一次。更新了代码。希望它可以帮助。谢谢!
-
好吧,你可以让所有的方法同步。也许您应该通过解释您的实际用例来扩展问题,因为这样呈现时看起来很简单。
-
每次访问 MyObject 实例时都可以使用
synchronized(obj)块。
标签: java multithreading concurrency