※集合
System.out.println("synchronized list"); List<Integer> l = new ArrayList<>(); synchronized (l) { l.add(1); l.add(2); l.add(3); } for (Integer i : l) { System.out.println(i); } System.out.println(); System.out.println("synchronizedCollection"); Collection<String> c = Collections.synchronizedCollection(new ArrayList<>()); c.add("A"); c.add("B"); c.add("C"); synchronized (c) { for (String s : c) { System.out.println(s); } } System.out.println(); System.out.println("synchronizedList"); List<String> list = Collections.synchronizedList(new ArrayList<>()); list.add("D"); list.add("E"); list.add("F"); synchronized (list) { for (String s : list) { System.out.println(s); } } System.out.println(); System.out.println("synchronizedSet"); Set<String> set = Collections.synchronizedSet(new HashSet<>()); set.add("G"); set.add("H"); set.add("G"); synchronized (set) { for (String s : set) { System.out.println(s); } } System.out.println(); System.out.println("synchronizedMap"); Map<Integer, String> map = Collections.synchronizedMap(new HashMap<>()); map.put(0, "A"); map.put(1, "B"); map.put(2, "C"); for (int i = 0; i < map.size(); i++) { System.out.println(map.get(i)); }
※這些是 java 1.5 之前的寫法,for 迴圈有用 synchronized ,是因為使用到 Iterator ,它並不是 Thread-safe,而 for each 會用到 Iterator 物件,但最原始的 for 迴圈不會用到
※ java 1.5 集合
System.out.println("CopyOnWriteArrayList"); List<String> list = new CopyOnWriteArrayList<>(); list.add("D"); list.add("E"); list.add("F"); for (String s : list) { System.out.println(s); } System.out.println(); System.out.println("CopyOnWriteArraySet"); Set<String> set = new CopyOnWriteArraySet<>(); set.add("G"); set.add("H"); set.add("G"); for (String s : set) { System.out.println(s); } System.out.println(); System.out.println("ConcurrentHashMap"); Map<Integer, String> map = new ConcurrentHashMap<>(); map.put(0, "A"); map.put(1, "B"); map.put(2, "C"); for (int i = 0; i < map.size(); i++) { System.out.println(map.get(i)); }
※java 1.5 新增了 java.util.concurrent 這個套件
※ThreadLocal
ThreadLocal 是 Thread 變數,在寫 Thread-safe 是很困難的,要讓 Thread 共用,又要同步,又有效能的問題,還要小心 Dead Lock,所以有人想到不要共用了,直接創造 Thread 的複本,在 java 1.2 就產生了 ThreadLocal 類別了,但此方法會需要較多的記憶體※
public class ThreadTest extends Thread { private static int number; public int getNumber() { number = number + 1; return number; } // private static ThreadLocal<Integer> number = new ThreadLocal<Integer>() { // @Override // protected Integer initialValue() { // return 0; // } // }; // public int getNumber() { // number.set(number.get() + 1); // return number.get(); // } @Override public void run() { for (int i = 1; i <= 3; i++) { System.out.println(Thread.currentThread().getName() + "=" + getNumber()); } } public static void main(String... a) { ThreadTest t1 = new ThreadTest(); ThreadTest t2 = new ThreadTest(); ThreadTest t3 = new ThreadTest(); t1.start(); t2.start(); t3.start(); } }
※結果:
Thread-0=1
Thread-0=4
Thread-0=5
Thread-1=3
Thread-1=6
Thread-1=7
Thread-2=2
Thread-2=8
Thread-2=9
可以看得出來 Thread 之間被影響了,應該三個 Thread 都是 123 才是正確的
※打開註解並註解原來的 number 和 getNumber(),結果如下:
Thread-0=1
Thread-0=2
Thread-0=3
Thread-2=1
Thread-2=2
Thread-2=3
Thread-1=1
Thread-1=2
Thread-1=3
沒有留言:
張貼留言