java多线程总结学习-Queue、容器、单例模式
来源:互联网 发布:pc蛋蛋幸运28算法技巧 编辑:程序博客网 时间:2024/06/14 08:16
1、单例模式支持多线程
单例模式:常用的两种模式:饿汉模式 懒汉模式,但这两种模式在多线程应用场景并不安全
为了适用于多线程,保障线程安全,用下面两种:double check instance、static inner class
(1)static inner class
package thread;/** * 单例模式,保障线程安全 * static inner class * 静态内部类形式 */public class SingleInner {private static class Singleton{private static Singleton single = new Singleton();}public static Singleton getInstance(){return Singleton.single;}}
(2)double check instance
public class Singleton{//私有静态实例,防止被引用private static Singleton instance = null;//私有构造方法,防止被实例化private Singleton(){}private static synchronized void syncInit(){if(instance == null){instance = new Singleton();}}public static Singleton getInstance(){if(instance == null){syncInit();}return instance;}}
2、同步类容器、并发类容器
同步类:vector hashTable(底层自带synchronid修饰,实现了同步,但是影响并发效率)并发类:Queue、concurrentMap、LinkedBlockingQueue、CopyOnWrite
(1)ConcurrentHashMap:
用段segment划分多个段,每个段相当于hashTable,有对应锁,最高支持16个段每个线程来的时候,访问不同的段
作用:减少锁粒度,减少锁竞争
底层大量使用volatile关键字,实现共享变量
(2)Copy-On-Write(COW)
CopyOnWriteArrayList和CopyOnWriteArraySet写时复制的容器、实现读写分离
当一个线程操作(增删改)容器时,不直接操作该容器,而是复制一个一模一样的容器进行操作,操作完成后,将原容器的指针指向复制的容器。
当有其他线程进行读时,直接读取原容器,实现读写相分离
应用场景:读多写少的时候
3、并发queue
ConcurentLinkedQueue:非阻塞的,性能高,高并发BlockingQueue:阻塞的
ConcurentLinkedQueue:
先进先出,头是最先的,尾是最近的,不允许有null值
add() offer()加入元素,在ConcurentLinkedQueue里没区别
poll() peek() 取头元素,前者删除元素,后者不删
BlockingQueue:,阻塞的
1、ArrayBlockingQueue,基于数组、有界队列,阻塞的
2、LinkedBlockingQueue 无界队列,阻塞的
3、synchronousQueue:没有缓冲的队列,不能添加元素
4、priorityBlockingQueue:基于优先级的阻塞队列,传入队列的对象必须实现comparable接口 不遵循先进先出
5、DelayQueue:元素必须实现delayed接口,元素必须到达延迟时间时,才会被取出
(1)ConcurentLinkedQueue
package queue;import java.util.concurrent.ConcurrentLinkedQueue;/** * ConcurrentLinkedQueue非阻塞的,性能高,高并发 * 先进先出,头是最先的,尾是最近的,不允许有null值 * add() offer()加入元素,在ConcurentLinkedQueue里没区别 * poll() peek() 取头元素,前者删除元素,后者不删 */public class UseConcurrentQueue {public static void main(String[] args) {ConcurrentLinkedQueue<String> q = new ConcurrentLinkedQueue<String>();q.add("a");q.add("b");q.add("c");q.add("d");q.offer("e");q.offer("f");System.out.println(q.size());System.out.println(q.poll());System.out.println(q.size());System.out.println(q.peek());System.out.println(q.size());}}
(2)BlockingQueue(ArrayBlockingQueue、linkedBlockingQueue、SynchronousQueue)
package queue;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.SynchronousQueue;/** * BlockingQueue:阻塞的 * ArrayBlockingQueue:基于数组的,有界的 * linkedBlockingQueue:无界的,在初始化时,给定长度,则是有界的,不给定长度,则是无界的 * SynchronousQueue:没有容量的队列,take()方法会进行阻塞,执行过take后,可以进行add,直接add会报错,因为没容量 * */public class UseBlockingQueue {public static void main(String[] args) throws Exception{//ArrayBlockingQueueArrayBlockingQueue<String> aq = new ArrayBlockingQueue<String>(5);aq.add("a");aq.add("b");aq.put("c");aq.put("d");aq.offer("e");aq.offer("f");System.out.println("ArrayBlockingQueue:"+aq);//linkedBlockingQueueLinkedBlockingQueue<String> lq = new LinkedBlockingQueue<>();lq.add("a");lq.add("b");lq.put("c");lq.put("d");lq.offer("e");lq.offer("f");System.out.println("LinkedBlockingQueue无界:"+lq);LinkedBlockingQueue<String> lq2 = new LinkedBlockingQueue<>(4);lq2.add("a");lq2.add("b");lq2.put("c");lq2.put("d");lq2.offer("e");lq2.offer("f");System.out.println("LinkedBlockingQueue有界:"+lq2);//synchronousQueuefinal SynchronousQueue<String> sq = new SynchronousQueue<>();//sq.add("a");//会报错java.lang.IllegalStateException: Queue fullThread t1 = new Thread(new Runnable(){@Overridepublic void run() {try {sq.take();} catch (InterruptedException e) {e.printStackTrace();}}});t1.start();Thread t2 = new Thread(new Runnable(){@Overridepublic void run() {sq.add("a");System.out.println("SynchronousQueue:"+sq);}});t2.start();}}
(3)PriorityBlockingQueue。模拟场景:当有任务时,会根据任务ID,按照优先级,进行释放
package queue;import java.util.concurrent.PriorityBlockingQueue;import queue.priority.Task;/** * PriorityBlockingQueue:优先级队列 * 队列里的元素必须继承comparable接口,并实现方法 * 当对队列进行take操作是,队列会根据优先级排序(不遵循先进先出) * */public class UsePriorityBlockingQueue {public static void main(String[] args) throws Exception{PriorityBlockingQueue<Task> pq = new PriorityBlockingQueue<Task>();Task t1 = new Task();t1.setId(1);t1.setName("任务1");Task t2 = new Task();t2.setId(4);t2.setName("任务2");Task t3 = new Task();t3.setId(3);t3.setName("任务3");pq.add(t1);pq.add(t2);pq.add(t3);System.out.println("容器:"+pq.toString());System.out.println(pq.take().getId());System.out.println("容器:"+pq.toString());System.out.println(pq.take().getId());System.out.println(pq.take().getId());}}
package queue.priority;public class Task implements Comparable<Task>{private int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic int compareTo(Task o) {return this.id > o.id ? 1 : (this.id > o.id ? -1 : 0);}public String toString(){return this.id + "," + this.name;}}
运行结果:
容器:[1,任务1, 4,任务2, 3,任务3]
1
容器:[3,任务3, 4,任务2]
3
4
(4)DelayQueue,模拟场景,网吧上机,到时间下机
package queue;import java.util.concurrent.DelayQueue;import queue.delay.Wangmin;/** * DelayQueue:延迟队列 * 元素必须实现delayed接口 * 元素必须到达延迟时间时,才会被取出 */public class UseDelayQueue implements Runnable{DelayQueue<Wangmin> dq = new DelayQueue<Wangmin>();public void shangji(int id, String name, int money){Wangmin wm = new Wangmin(id,name,1000*money+System.currentTimeMillis());dq.add(wm);System.out.println("网民:"+name+"开始上机,上机时间"+money+"秒");}public void xiaji(Wangmin wm){System.out.println("网民:"+wm.getName()+"下机。。。");}@Overridepublic void run() {while(true){try {Wangmin wm = dq.take();xiaji(wm);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {UseDelayQueue udq = new UseDelayQueue();Thread t = new Thread(udq);t.start();udq.shangji(1,"张三",1);udq.shangji(2,"李四",10);udq.shangji(3,"王五",5);}}
package queue.delay;import java.util.concurrent.Delayed;import java.util.concurrent.TimeUnit;/** * 网民 * 实现了Delayed接口 * 需要实现getDelay、compareTo方法 */public class Wangmin implements Delayed{private int id;private String name;private long endtime;private TimeUnit timeUnit = TimeUnit.SECONDS;//时间单位,秒//构造方法public Wangmin(int id, String name, long endtime){this.id=id;this.name = name;this.endtime = endtime;}@Overridepublic int compareTo(Delayed delay) {Wangmin w = (Wangmin)delay;return this.getDelay(this.timeUnit) > w.getDelay(this.timeUnit) ? 1 : 0;}@Overridepublic long getDelay(TimeUnit arg0) {return endtime - System.currentTimeMillis();}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public long getEndtime() {return endtime;}public void setEndtime(long endtime) {this.endtime = endtime;}}
运行结果:
网民:张三开始上机,上机时间1秒
网民:李四开始上机,上机时间10秒
网民:王五开始上机,上机时间5秒
网民:张三下机。。。
网民:王五下机。。。
网民:李四下机。。。
网民:李四开始上机,上机时间10秒
网民:王五开始上机,上机时间5秒
网民:张三下机。。。
网民:王五下机。。。
网民:李四下机。。。
阅读全文
0 0
- java多线程总结学习-Queue、容器、单例模式
- 黑马程序员-Java基础-多线程之单例模式总结
- java多线程单例模式
- java多线程单例模式
- java 多线程单例模式
- Java多线程总结之Queue
- Java中的设计模式学习总结(二)---单例模式
- Java设计模式(1)之单例模式学习总结
- 单例模式学习总结
- 单例模式学习总结
- 单例模式学习总结
- 【java多线程编程核心技术】6.单例模式与多线程-笔记总结
- JAVA单例模式总结
- java单例模式总结
- java单例模式总结
- Java容器学习:List、Set、Queue、Map
- Java 多线程下的单例模式
- Java 多线程下的单例模式
- Android 事件分发机制分析
- JavaWeb(四)EL表达式
- 写过的代码笔记
- Linux应用层的i2c读写
- xcode里面找不到头文件
- java多线程总结学习-Queue、容器、单例模式
- CentOS 下配置 MongoDB 为服务
- Windows程序设计-动态链接库
- Linux ALSA声卡驱动之五:移动设备中的ALSA
- 一张图理清ASP.NET Core启动流程
- Flex 布局教程:语法篇 作者: 阮一峰
- 获取SD卡的唯一标识
- 【原创】流程引擎的网关(遵循BPMN2.0)设计总结
- Fiddler抓包教程