我正面临这个问题,我有两个A和B类,'A类'有两个主题t1和t2,它试图访问'B类'地图,如下所示问题是,我不能做任何修改因为我不能使用synchronised
关键字,或者我不能将它放在同步方法中。所以我的疑问是,还有其他方法来同步这张地图。
public class A{
static B b = new B();
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
Map<Integer,String> map = Collections.synchronizedMap(b.getMap());
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
b.setMap(map);
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
Map<Integer,String> map = Collections.synchronizedMap(b.getMap());
map.put(4, "four");
map.put(5, "five");
map.put(6, "six");
b.setMap(map);
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(Map.Entry<Integer, String> entry : b.getMap().entrySet()){
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
我正在使用LinkedHashMap
,仅用于跟踪插入顺序(忽略性能问题)
public class B{
private Map<Integer,String> map = new LinkedHashMap<Integer,String>();
public Map<Integer,String> getMap() {
return map;
}
public void setMap(Map<Integer,String> map) {
this.map = map;
}
}
答案 0 :(得分:2)
您可以创建一次同步Map
并让两个线程都使用该Map
个实例。
final Map<Integer,String> map = Collections.synchronizedMap(b.getMap());
b.setMap(map);
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
map.put(4, "four");
map.put(5, "five");
map.put(6, "six");
}
});
答案 1 :(得分:1)
为什么不在B中设置地图。如果您无法使用ConcurrentHashMap
,则可以使用Collections.synchronizedMap(new LinkedHashMap<>())
代替。任何外部同步都将始终存在对映射进行不同步访问的可能性。
public class A{
static B b;
static {
b = new B();
b.setMap(new ConcurrentHashMap());
}
//...
}
答案 2 :(得分:1)
正如其他人指出的那样,您可以使用同步包装器,而java.util.Collections
提供了一种方便的方法来获取一个。但是,让每个线程获得自己的同步包装对你没有帮助 - 所有参与者都需要使用相同的同步工具。
更一般地说,如果您需要同步访问一些不太方便的对象,那么您可以使用外部同步。在您的情况下,可能如下所示:
public class A{
static B b = new B();
// will use this object to synchronize access to b's map:
static Object bLock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
Map<Integer,String> map = b.getMap();
synchronized(bLock) {
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
}
// no need for setMap()
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
Map<Integer,String> map = b.getMap();
synchronized (bLock) {
map.put(4, "four");
map.put(5, "five");
map.put(6, "six");
}
// no need for setMap()
}
});
// ...
}
}
包java.util.concurrent.locks也有一些你可以使用的锁类,但通常你不需要任何这么花哨的东西。
答案 3 :(得分:0)
简单地:
public class A{
static B b;
static Map bMap;
static {
b = new B();
bMap = Collections.synchronizedMap(b.getMap());
}
... //now use bMap instead
}