百知教育 - 孙帅 - 16_多线程(续)
14_深入比较ArrayList和Vector
-
Collections工具类中提供了多个可以获得线程安全集合的方法(均以synchronized实现):
- public static < T > Collection synchronizedCollection(Collection c)
- public static < T > List< T > synchronizedList(List< T > list)
- public static < T > Set< T > synchronizedSet(Set< T > s)
- public static < K, V > Map< K, V > synchronizedMap(Map< K, V > m)
- public static < T > SortedSet< T > synchronizedSortedSet(SortedSet< T > s)
- public static < K, V > SortedMap< K, V > synchronizedSortedMap(SortedMap< K, V > m)
-
代码(编译通过):
package day20; import java.util.ArrayList; import java.util.List; import java.util.HashSet; import java.util.Set; import java.util.Collections; public class TestThreadSafe{ public static void main(String[] args){ Set<String> s1 = new HashSet<>(); //线程不安全 Set<String> s2 = Collections.synchronizedSet(s1); //线程安全 List<String> l1 = new ArrayList<>(); List<String> l2 = Collections.synchronizedList(l1); } }
15_ReadWriteLock
-
读写锁
- ReentrantReadWriteLock:
- 一种支持一写多读的同步锁,读写分离,可分别分配读锁、写锁。
- 支持多次分配读锁,使多个读操作可以并发执行。
- 互斥规则:
- 写-写: 互斥,阻塞
- 读-写: 互斥,读阻塞写,写阻塞读
- 读-读: 不互斥,不阻塞
- 在读操作远远高于写操作的环境中,可在保障线程安全的情况下,提高运行效率。
- ReentrantReadWriteLock:
-
代码(编译通过):
package day20; import java.util.ArrayList; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class TestReadWriteLock{ public static void main(String[] args){ } } class MyList extends ArrayList{ ReadWriteLock rwl = new ReentrantReadWriteLock(); Lock rl = rwl.readLock(); Lock wl = rwl.writeLock(); @Override public int size(){ try{ rl.lock(); return super.size(); } finally{ rl.unlock(); } } @Override public Object get(int index){ try{ rl.lock(); return super.get(index); } finally{ rl.unlock(); } } @Override public boolean add(Object o){ try{ wl.lock(); return super.add(o); } finally{ wl.unlock(); } } @Override public Object remove(int index){ try{ wl.lock(); return super.remove(index); } finally{ wl.unlock(); } } @Override public void clear(){ try{ wl.lock(); super.clear(); } finally{ wl.unlock(); } } }
16_高级的线程安全的集合
-
java.util.concurrent.*
- CopyOnWriteArrayList: 利用复制数组的方式实现数组元素的修改,写效率低,读效率高(基于“读操作远多于写操作”)
- CopyOnWriteArraySet
- ConcurrentHashMap: 分段锁
- ConcurrentLinkedQueue: 线程安全的队列(链表实现) ,利用无锁算法(CAS:比较交换算法)实现线程安全
17_BlockingQueue
-
BlockingQueue(阻塞队列)
- 方法:
- put(): 添加元素到队列中,如果队列满,则等待。
- take(): 删除队头元素,如果队列空,则等待。
- 实现类:
- ArrayBlockingQueue: 数组实现,有界队列,put方法可能等待
- LinkedBlockingQueue: 链表实现,无界队列,put方法不可能等待
- 方法:
-
代码:
package day21; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class TestBlockingQueue{ public static void main(String[] args){ BlockingQueue<String> queue = new ArrayBlockingQueue<String>(6); Runnable task1 = new Runnable(){ public void run(){ for(int i = 1; i <= 10; i++){ try{ queue.put("A"+i); System.out.print("A"+i+"put "); for(String s : queue){ System.out.print(s+" "); } System.out.println(); }catch(InterruptedException e){ e.printStackTrace(); } } } }; Runnable task2 = new Runnable(){ public void run(){ for(int i = 1; i <= 10; i++){ try{ queue.take(); System.out.println("A"+i+"take "); for(String s : queue){ System.out.print(s+" "); } System.out.println(); }catch(InterruptedException e){ e.printStackTrace(); } } } }; ExecutorService es = Executors.newFixedThreadPool(2); es.submit(task1); es.submit(task2); es.shutdown(); } }
-
运行结果:
18_集合接口和类的总结
-
Collection
- List (ArrayList, LinkedList, Vector, CopyOnWriteArrayList)
- Set (HashSet, Hashtable, CopyOnWriteArraySet)
- SortedSet (TreeSet)
- Queue (LinkedList, ConcurrentLinkedQueue)
- BlockingQueue (ArrayBlockingQueue, LinkedBlockingQueue)
-
Map (HashMap, Hashtable, Properties, ConcurrentHashMap)
- SortedMap (TreeMap)
19_Atomiclnteger
-
代码:
package day21; import java.util.concurrent.atomic.AtomicInteger; public class TestAtomicInteger{ static int i = 0; static AtomicInteger ai = new AtomicInteger(0); public static void main(String[] args) throws Exception{ Thread[] ts = new Thread[10]; for(int k = 0; k < ts.length; k++){ ts[k] = new Thread(new Runnable(){ public void run(){ for(int k = 1; k <= 10000; k++){ i++; ai.incrementAndGet(); } } }); ts[k].start(); } for(int k = 0; k < ts.length; k++){ ts[k].join(); } System.out.println(i); System.out.println(ai); } }
-
运行结果:
20_int原子操作的加锁算法
-
代码:
package day21; import java.util.concurrent.atomic.AtomicInteger; public class TestIntegerLock{ static int i = 0; //error! static AtomicInteger ai = new AtomicInteger(0); //效率最高 static Integer b = Integer.valueOf(0); //error! --> 没有临界资源(锁住的不是同一个对象) static MyObject obj = new MyObject(); //效率低 public static void main(String[] args) throws Exception{ Thread[] ts = new Thread[10]; for(int k = 0; k < ts.length; k++){ ts[k] = new Thread(new Runnable(){ public void run(){ for(int k = 1; k <= 10000; k++){ i++; ai.incrementAndGet(); synchronized(b){ b = Integer.valueOf(b.intValue()+1); } synchronized(obj){ obj.x++; } } } }); ts[k].start(); } for(int k = 0; k < ts.length; k++){ ts[k].join(); } System.out.println(i); System.out.println(ai); System.out.println(b); System.out.println(obj.x); } } class MyObject{ int x = 0; }
-
运行结果:
21_ForkJoin_Recursive Task(分治归并算法)
-
代码:
package day21; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask; public class TestForkJoinAdd{ public static void main(String[] args){ ForkJoinPool pool = new ForkJoinPool(); AddTask main = new AddTask(1, 100000); Long result = pool.invoke(main); System.out.println(result); } } class AddTask extends RecursiveTask<Long>{ int start; int end; static final int THRESHOLD = 5000; public AddTask(int start, int end){ super(); this.start = start; this.end = end; } @Override public Long compute(){ //如果start和end之间差距低于THRESHOLD,直接计算 if(end - start <= THRESHOLD){ long result = 0; for(int i = start; i <= end; i++){ result += i; } return result; } //否则就要把任务分割为两个子任务 else{ int middle = (start+end)/2; AddTask task1 = new AddTask(start, middle); AddTask task2 = new AddTask(middle+1, end); invokeAll(task1, task2); long r1 = task1.join(); long r2 = task2.join(); return r1+r2; } } }
-
运行结果:
22_ForkJoin_RecursiveAction
-
代码:
package day21; import java.util.concurrent.ForkJoinPool; import java.util.Arrays; import java.util.concurrent.RecursiveAction; import java.util.Random; public class TestForkJoinSort{ public static void main(String[] args){ Random random = new Random(); int[] data = new int[5000000]; for(int i = 0; i < data.length; i++){ data[i] = random.nextInt(5000000); } ForkJoinPool pool = new ForkJoinPool(); MySortTask main = new MySortTask(data, 0, data.length); pool.invoke(main); for(int i = 0; i < 10; i++){ System.out.println(data[i]); } } } class MySortTask extends RecursiveAction{ int[] data; int start; int end; static final int THRESHOLD = 1000; public MySortTask(int[] data, int start, int end){ super(); this.data = data; this.start = start; this.end = end; } public void compute(){ if(start - end <= THRESHOLD){ Arrays.sort(data, start, end); } else{ int middle = (start + end)/2; MySortTask task1 = new MySortTask(data, start, middle); MySortTask task2 = new MySortTask(data, middle, end); invokeAll(task1, task2); merge(middle); } } public void merge(int middle){ int[] a = Arrays.copyOfRange(data, start, middle); int[] b = Arrays.copyOfRange(data, middle, end); int x = 0; int y = 0; for(int i = start; i < end; i++){ if(x == a.length) data[i] = b[y++]; else if(y == b.length) data[i] = a[x++]; else if(a[x] < b[y]) data[i] = a[x++]; else data[i] = b[y++]; } } }
-
运行结果:
23_利用ForkJoin计算数组最大值
-
代码:
package day21; import java.util.Random; import java.util.concurrent.RecursiveTask; import java.util.concurrent.ForkJoinPool; public class TestForkJoinMax1{ public static void main(String[] args){ Random random = new Random(); int[] data = new int[40000000]; for(int i = 0 ; i < data.length ; i++){ data[i] = random.nextInt(100000000); } System.out.println(findMax1(data)); System.out.println(findMax2(data , 0 , data.length)); } static int findMax1(int[] data){ long t1 = System.currentTimeMillis(); int max = data[0]; for(int i = 0 ; i < data.length ; i++){ if(max < data[i]) max = data[i]; } long t2 = System.currentTimeMillis(); System.out.println(t2-t1); return max; } static int findMax2(int[] data , int start , int end){ class MaxTask extends RecursiveTask<Integer>{ int[] data; int start; int end; static final int THRESHOLD = 100000; public MaxTask(int[] data , int start , int end){ super(); this.data = data; this.start = start; this.end = end; } public Integer compute(){ if(start - end <= THRESHOLD){ int max = data[0]; for(int i = start ; i < end ; i++){ if(data[i] > max) max = data[i]; } return max; } else{ int middle = (start+end)/2; MaxTask task1 = new MaxTask(data , start , middle); MaxTask task2 = new MaxTask(data , middle , end); invokeAll(task1 , task2); int max1 = task1.join(); int max2 = task2.join(); if(max1 > max2) return max1; else return max2; } } } long t1 = System.currentTimeMillis(); ForkJoinPool pool = new ForkJoinPool(); MaxTask main = new MaxTask(data , start , end); long t2 = System.currentTimeMillis(); System.out.println(t2-t1); return pool.invoke(main); } }
-
运行结果:
24_Semaphore
-
代码:
package day21; import java.util.List; import java.util.ArrayList; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicBoolean; public class TestSemaphore{ public static void main(String[] args){ List<PhoneRoom> rooms = new ArrayList<>(); rooms.add(new PhoneRoom("room1")); rooms.add(new PhoneRoom("room2")); rooms.add(new PhoneRoom("room3")); rooms.add(new PhoneRoom("room4")); rooms.add(new PhoneRoom("room5")); Semaphore s = new Semaphore(5); class Task implements Runnable{ public void run(){ try{ s.acquire(); }catch(InterruptedException e){ e.printStackTrace(); } for(int i = 0 ; i < rooms.size() ; i++){ PhoneRoom room = rooms.get(i); if(room.isFree()){ room.setFree(false); System.out.println(Thread.currentThread().getName()+" entered "+room.getName()); try{ Thread.sleep(2000); }catch(InterruptedException e){ e.printStackTrace(); } room.setFree(true); System.out.println(Thread.currentThread().getName()+" exited "+room.getName()); s.release(); return; } } } }; //Task task = new Task(); for(int i = 1 ; i <= 10 ; i++){ Task task = new Task(); Thread ts = new Thread(task); ts.start(); } } } class PhoneRoom{ private AtomicBoolean isFree = new AtomicBoolean(true); private String name; public PhoneRoom(String name){ this.name = name; } public boolean isFree(){ return isFree.get(); } public void setFree(boolean flag){ isFree.set(flag); } public String getName(){ return name; } }
-
运行结果:
25_CountDownLatch
-
代码:
package day21; import java.util.concurrent.CountDownLatch; public class TestCountDownLatch{ public static void main(String[] args){ CountDownLatch cdl = new CountDownLatch(2); Thread t1 = new Thread(){ public void run(){ for(int i = 0 ; i < 5 ; i++){ if(i == 2) cdl.countDown(); System.out.println("@@@ "+i); try{ Thread.sleep(100); }catch(InterruptedException e){ e.printStackTrace(); } } } }; Thread t2 = new Thread(){ public void run(){ for(int i = 0 ; i < 5 ; i++){ if(i == 2) cdl.countDown(); System.out.println("### "+i); try{ Thread.sleep(100); }catch(InterruptedException e){ e.printStackTrace(); } } } }; Thread t3 = new Thread(){ public void run(){ try{ cdl.await(); }catch(InterruptedException e){ e.printStackTrace(); } for(int i = 0 ; i < 5 ; i++){ System.out.println("$$$ "+i); try{ Thread.sleep(100); }catch(InterruptedException e){ e.printStackTrace(); } } } }; t1.start(); t2.start(); t3.start(); } }
-
运行结果:
26_CyclicBarrier
-
代码:
package day21; import java.util.concurrent.CyclicBarrier; public class TestCyclicBarrier{ public static void main(String[] args){ CyclicBarrier cb = new CyclicBarrier(3); class Travel extends Thread{ String name; String city; int time; public Travel(String name , String city , int time){ this.name = name; this.city = city; this.time = time; } public void run(){ System.out.println(name+" 从 "+city+" 出发"); try{ Thread.sleep(time); System.out.println(name+" 到达北京"); cb.await(); }catch(Exception e){ e.printStackTrace(); } System.out.println(name+" 去爬长城"); } } Travel t1 = new Travel("YKY" , "天津" , 2000); Travel t2 = new Travel("LYH" , "黑龙江" , 5000); Travel t3 = new Travel("HHH" , "拉萨" , 10000); t1.start(); t2.start(); t3.start(); } }
-
运行结果: