我们都知道,Java中常用的集合框架中的实现类HashSet、TreeSet、ArrayList、ArrayDeque、LinkedList、HashMap、TreeMap都是线程不安全的,如果有多个线程同时访问它们,且同时有多个线程修改他们的时候,将会出现如读脏数据等错误。Collections提供了synchronizedXxx()方法来帮助其实现线程安全。下面给出代码演示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class TestSynchronized {
static Collection cl = Collections
.synchronizedCollection(new ArrayList());
static List list = Collections
.synchronizedList(new ArrayList());
static Set set = Collections.synchronizedSet(new HashSet());
static Map map = Collections
.synchronizedMap(new HashMap());
static boolean run = true;
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread a = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("*******This is a thread********");
System.out.println("Is Collection add element successfully? "
+ (cl.add("lan") ? "Yes" : "No"));
System.out.println("Is List add element successfully? "
+ (list.add(33) ? "Yes" : "No"));
System.out.println("Is Set add element successfully? "
+ (set.add("lan") ? "Yes" : "No"));
System.out
.println("Map put element successfully. The element value is:"
+ map.put("lan", 33));
}
});
Thread b = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("*******This is b thread********");
System.out.println("Is Collection add element successfully? "
+ (cl.add("lan") ? "Yes" : "No"));
System.out.println("Is List add element successfully? "
+ (list.add(33) ? "Yes" : "No"));
System.out.println("Is Set add element successfully? "
+ (set.add("lan") ? "Yes" : "No"));
System.out
.println("Map put element successfully. The element value is:"
+ map.put("lan", 33));
}
});
Thread c = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("*******This is c thread********");
System.out.println("Is Collection add element successfully? "
+ (cl.add("lan") ? "Yes" : "No"));
System.out.println("Is List add element successfully? "
+ (list.add(33) ? "Yes" : "No"));
System.out.println("Is Set add element successfully? "
+ (set.add("lan") ? "Yes" : "No"));
System.out
.println("Map put element successfully. The element value is:"
+ map.put("lan", 33));
}
});
a.start();
b.start();
c.start();
Thread d = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("cl----->" + cl);
System.out.println("list----->" + list);
System.out.println("set----->" + set);
System.out.println("map----->" + map);
}
});
while (run) {
if ((!a.isAlive()) && (!b.isAlive()) && (!c.isAlive())) {
if (!d.isAlive()){
run = false;
d.start();
}
}
}
}
}
运行结果:
*******This is a thread********
Is Collection add element successfully? Yes
Is List add element successfully? Yes
Is Set add element successfully? Yes
Map put element successfully. The element value is:null
*******This is c thread********
Is Collection add element successfully? Yes
Is List add element successfully? Yes
Is Set add element successfully? No
Map put element successfully. The element value is:33
*******This is b thread********
Is Collection add element successfully? Yes
Is List add element successfully? Yes
Is Set add element successfully? No
Map put element successfully. The element value is:33
cl----->[lan, lan, lan]
list----->[33, 33, 33]
set----->[lan]
map----->{lan=33}
由此可以看出,无论线程如何修改资源,我们将得到最新的值,不会出现读脏数据。