wait与notify实现阻塞队列
同步类容器在迭代的过程中如果被并发修改了内容,会抛出ConcurrentModificationException
同步类容器的状态都是串行化的
ConcurrentHashMap代替Hashtable
CopyOnWriteArrayList代替Vector
并发的CopyOnWriteArraySet
ConcurrentLinkedQueue——高性能队列
LinkedBlockingQueue——阻塞形式的队列
ArrayBlockingQueue,PriorityBlockingQueue,SynchronousQueue
ConcurrentHashMap
ConcurrentSkipListMap(支持并发排序功能,弥补ConcurrentHashMap)
ConcurrentHashMap 内部 16个段(Segment),减少锁的粒度降低锁竞争,不在一个段上的写操作可以并发进行,共享变量被volatile修饰,不会出现脏读
Copy-On-Write容器
写时复制容器,添加元素,并不直接添加,而是复制当前容器,在新的容器里添加元素,再把原容器的引用指向新的容器
并发的读不需要加锁,读写分离的思想,适合读多写少的场景
ConcurrentLinkedQueue
通过无锁的方式,实现了高并发状态下的高性能。它是一个基于链表的无界线程安全队列,遵循FIFO原则,头是最先加入的,尾是最近加入的,不允许null元素且在通常情况下性能要好于BlockingQueue
ArrayBlockingQueue:基于数组的阻塞队列,内部维护一个定长数组(长度是需要定义的),以便缓存队列中的数据对象,其内部没有实现读写分离,也就意味着生产和消费不能完全并行,可以指定先进先出或者先进后出,是一个有界队列
LinkedBlockingQueue:基于链表的阻塞队列,其内部也维护着一个数据缓冲列队。它之所以能够高效的处理并发数据,是因为其内部用分离锁(读写分离两个锁)实现,从而实现生产者和消费者操作的完全并行运行,是一个无界队列(含参构造初始化则是有界的)
PriorityBlockingQueue:基于优先级的阻塞队列(优先级的判断通过构造函数传入的Compator对象来决定,也就是说传入队列的对象必须实现Comparable接口),内部控制线程同步的锁是公平锁,是一个无界队列
SynchronousQueue:一种没有缓冲的队列,生产者产生的数据直接会被消费者获取并消费
DelayQueue:带有延迟时间的Queue,其中的元素只有当其指定的延迟时间到了,才能够从队列中获取到元素。DelayQueue中的元素必须实现Delayed接口,是一个无界队列,主要用于对缓存超时数据进行移除、任务超时处理、空闲连接的关闭等
1 package concurrent; 2 3 import java.util.concurrent.Delayed; 4 import java.util.concurrent.TimeUnit; 5 6 public class Wangmin implements Delayed { 7 private String name; 8 private String id;// 身份证 9 private long endTime;// 截止时间 10 private TimeUnit timeUnit = TimeUnit.SECONDS;// 定义时间工具类 11 12 public Wangmin(String name,String id,long endTime){ 13 this.name=name; 14 this.id=id; 15 this.endTime = endTime; 16 } 17 18 public String getName(){ 19 return this.name; 20 } 21 22 public String getId(){ 23 return this.id; 24 } 25 26 //判断是否到了截止时间 27 @Override 28 public long getDelay(TimeUnit unit) { 29 return endTime - System.currentTimeMillis(); 30 } 31 @Override 32 public int compareTo(Delayed delayed) { 33 Wangmin w = (Wangmin)delayed; 34 return this.getDelay(this.timeUnit) > w.getDelay(this.timeUnit) ? 1:0; 35 } 36 37 }
1 package concurrent; 2 3 import java.util.concurrent.DelayQueue; 4 5 public class WangBa implements Runnable { 6 private DelayQueue<Wangmin> queue = new DelayQueue<>(); 7 public boolean yinye =true; 8 9 public void shangji(String name,String id,int money){ 10 Wangmin man = new Wangmin(name, id, 1000 * money + System.currentTimeMillis()); 11 System.out.println(man.getName()+" 身份证"+man.getId()+"交钱"+money+"块,开始上机..."); 12 this.queue.add(man); 13 } 14 15 public void xiaji(Wangmin man){ 16 System.out.println(man.getName()+" 身份证"+man.getId()+"时间到下机..."); 17 } 18 19 @Override 20 public void run() { 21 while(yinye){ 22 try { 23 Wangmin man = queue.take(); 24 xiaji(man); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 } 29 } 30 31 public static void main(String args[]){ 32 try{ 33 System.out.println("网吧开始营业"); 34 WangBa siyu = new WangBa(); 35 Thread shangwang = new Thread(siyu); 36 shangwang.start(); 37 siyu.shangji("路人A", "123", 1); 38 siyu.shangji("路人B", "234", 10); 39 siyu.shangji("路人C", "345", 5); 40 } 41 catch(Exception e){ 42 e.printStackTrace(); 43 } 44 } 45 46 }
Future模式
1 package concurrent; 2 3 public interface Data { 4 String getRequest(); 5 }
1 package concurrent; 2 3 public class FutureClient { 4 public Data request(final String queryStr){ 5 final FutureData futureData = new FutureData(); 6 7 new Thread(new Runnable() { 8 @Override 9 public void run() { 10 RealData realData = new RealData(queryStr); 11 futureData.setRealData(realData); 12 } 13 }).start(); 14 return futureData; 15 } 16 }
1 package concurrent; 2 3 public class FutureData implements Data { 4 private RealData realData ; 5 private boolean isReady = false; 6 7 public synchronized void setRealData(RealData realData) { 8 if(isReady){ 9 return; 10 } 11 this.realData = realData; 12 isReady = true; 13 notify(); 14 } 15 @Override 16 public synchronized String getRequest() { 17 while(!isReady){ 18 try { 19 wait(); 20 } catch (InterruptedException e) { 21 e.printStackTrace(); 22 } 23 } 24 return this.realData.getRequest(); 25 } 26 }
1 package concurrent; 2 3 public class RealData implements Data { 4 private String result ; 5 6 public RealData (String queryStr){ 7 System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作.."); 8 try { 9 Thread.sleep(5000); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 System.out.println("操作完毕,获取结果"); 14 result = "查询结果"; 15 } 16 17 @Override 18 public String getRequest() { 19 return result; 20 } 21 22 }
1 package concurrent; 2 3 public class Main { 4 public static void main(String[] args) throws InterruptedException { 5 FutureClient fc = new FutureClient(); 6 Data data = fc.request("请求参数"); 7 System.out.println("请求发送成功!"); 8 System.out.println("去完成其他的事情..."); 9 String result = data.getRequest(); 10 System.out.println(result); 11 } 12 } 13 /* 14 请求发送成功! 15 去完成其他的事情... 16 根据请求参数进行查询,这是一个很耗时的操作.. 17 操作完毕,获取结果 18 查询结果 19 */
Master-Worker模式
1 package concurrent; 2 3 public class Task { 4 private int id; 5 private int price ; 6 7 public int getId() { 8 return id; 9 } 10 public void setId(int id) { 11 this.id = id; 12 } 13 public int getPrice() { 14 return price; 15 } 16 public void setPrice(int price) { 17 this.price = price; 18 } 19 20 }
1 package concurrent; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 import java.util.concurrent.ConcurrentHashMap; 6 import java.util.concurrent.ConcurrentLinkedQueue; 7 8 public class Master { 9 //1.盛放任务的容器 10 private ConcurrentLinkedQueue<Task> workQueue = new ConcurrentLinkedQueue<>(); 11 //2.盛放worker的集合 12 private HashMap<String, Thread> workers = new HashMap<>(); 13 //3.盛放每一个worker执行任务的结果集合 14 private ConcurrentHashMap<String, Object> resultMap = new ConcurrentHashMap<>(); 15 16 //4.构造方法 17 public Master(Worker worker , int workerCount){ 18 worker.setWorkQueue(this.workQueue); 19 worker.setResultMap(this.resultMap); 20 for(int i = 0; i < workerCount; i ++){ 21 this.workers.put(Integer.toString(i), new Thread(worker)); 22 } 23 } 24 //5.提交任务的方法 25 public void submit(Task task){ 26 this.workQueue.add(task); 27 } 28 //6.执行的方法,启动所有的worker方法去执行任务 29 public void execute(){ 30 for(Map.Entry<String, Thread> me : workers.entrySet()){ 31 me.getValue().start(); 32 } 33 } 34 //7.判断是否运行结束的方法 35 public boolean isComplete() { 36 for(Map.Entry<String, Thread> me : workers.entrySet()){ 37 if(me.getValue().getState() != Thread.State.TERMINATED){ 38 return false; 39 } 40 } 41 return true; 42 } 43 //8.计算结果方法 44 public int getResult() { 45 int priceResult = 0; 46 for(Map.Entry<String, Object> me : resultMap.entrySet()){ 47 priceResult += (Integer)me.getValue(); 48 } 49 return priceResult; 50 } 51 }
1 package concurrent; 2 3 import java.util.concurrent.ConcurrentHashMap; 4 import java.util.concurrent.ConcurrentLinkedQueue; 5 6 public class Worker implements Runnable { 7 private ConcurrentLinkedQueue<Task> workQueue; 8 private ConcurrentHashMap<String, Object> resultMap; 9 10 public void setWorkQueue(ConcurrentLinkedQueue<Task> workQueue) { 11 this.workQueue = workQueue; 12 } 13 public void setResultMap(ConcurrentHashMap<String, Object> resultMap) { 14 this.resultMap = resultMap; 15 } 16 @Override 17 public void run() { 18 while(true){ 19 Task input = this.workQueue.poll(); 20 if(input == null) break; 21 Object output = handle(input); 22 this.resultMap.put(Integer.toString(input.getId()), output); 23 } 24 } 25 private Object handle(Task input) { 26 Object output = null; 27 try { 28 //处理任务的耗时,比如说进行数据库操作... 29 Thread.sleep(500); 30 output = input.getPrice(); 31 } catch (InterruptedException e) { 32 e.printStackTrace(); 33 } 34 return output; 35 } 36 37 }
package concurrent; import java.util.Random; public class Main { public static void main(String[] args) { Master master = new Master(new Worker(), 20); Random r = new Random(); for(int i = 1; i <= 100; i++){ Task t = new Task(); t.setId(i); t.setPrice(r.nextInt(1000)); master.submit(t); } master.execute(); long start = System.currentTimeMillis(); while(true){ if(master.isComplete()){ long end = System.currentTimeMillis() - start; int priceResult = master.getResult(); System.out.println("最终结果:" + priceResult + ", 执行时间:" + end); break; } } } }
生产者-消费者模式
1 package concurrent; 2 3 public final class Data { 4 private String id; 5 private String name; 6 7 public Data(String id, String name){ 8 this.id = id; 9 this.name = name; 10 } 11 public String getId() { 12 return id; 13 } 14 public void setId(String id) { 15 this.id = id; 16 } 17 public String getName() { 18 return name; 19 } 20 public void setName(String name) { 21 this.name = name; 22 } 23 @Override 24 public String toString(){ 25 return "{id: " + id + ", name: " + name + "}"; 26 } 27 28 }
1 package concurrent; 2 3 import java.util.Random; 4 import java.util.concurrent.BlockingQueue; 5 import java.util.concurrent.TimeUnit; 6 import java.util.concurrent.atomic.AtomicInteger; 7 8 public class Provider implements Runnable{ 9 private BlockingQueue<Data> queue; 10 private volatile boolean isRunning = true; 11 private static AtomicInteger count = new AtomicInteger(); 12 private static Random r = new Random(); 13 14 public Provider(BlockingQueue queue){ 15 this.queue = queue; 16 } 17 @Override 18 public void run() { 19 while(isRunning){ 20 try { 21 Thread.sleep(r.nextInt(1000)); 22 int id = count.incrementAndGet(); 23 Data data = new Data(Integer.toString(id), "数据" + id); 24 System.out.println("线程:" + Thread.currentThread().getName() + "获取了数据,id为:" + id + "装载到公共缓冲区中..."); 25 if(!this.queue.offer(data, 2, TimeUnit.SECONDS)){ 26 System.out.println("提交缓冲区数据失败..."); 27 //do something... 28 } 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 public void stop(){ 35 this.isRunning = false; 36 } 37 }
1 package concurrent; 2 3 import java.util.Random; 4 import java.util.concurrent.BlockingQueue; 5 6 public class Consumer implements Runnable{ 7 private BlockingQueue<Data> queue; 8 public Consumer(BlockingQueue queue){ 9 this.queue = queue; 10 } 11 private static Random r = new Random(); 12 13 @Override 14 public void run() { 15 while(true){ 16 try { 17 Data data = this.queue.take(); 18 Thread.sleep(r.nextInt(1000)); 19 System.out.println("消费线程:" + Thread.currentThread().getName() + "消费成功,消费数据id为:" + data.getId()); 20 } catch (InterruptedException e) { 21 e.printStackTrace(); 22 } 23 } 24 } 25 }
1 package concurrent; 2 3 import java.util.concurrent.BlockingQueue; 4 import java.util.concurrent.ExecutorService; 5 import java.util.concurrent.Executors; 6 import java.util.concurrent.LinkedBlockingQueue; 7 8 public class Main { 9 public static void main(String[] args) throws Exception { 10 BlockingQueue<Data> queue = new LinkedBlockingQueue<>(10); 11 12 Provider p1 = new Provider(queue); 13 Provider p2 = new Provider(queue); 14 Provider p3 = new Provider(queue); 15 16 Consumer c1 = new Consumer(queue); 17 Consumer c2 = new Consumer(queue); 18 Consumer c3 = new Consumer(queue); 19 20 ExecutorService cachePool = Executors.newCachedThreadPool(); 21 cachePool.execute(p1); 22 cachePool.execute(p2); 23 cachePool.execute(p3); 24 cachePool.execute(c1); 25 cachePool.execute(c2); 26 cachePool.execute(c3); 27 try { 28 Thread.sleep(3000); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 p1.stop(); 33 p2.stop(); 34 p3.stop(); 35 try { 36 Thread.sleep(2000); 37 } catch (InterruptedException e) { 38 e.printStackTrace(); 39 } 40 } 41 }