目录
单例模式
饿汉模式
懒汉模式
阻塞队列
生产者-消费者模型意义
定时器
单例模式
单例模式就是,约定某个类,只能有一个实例,通过编码技巧,让编译器强制检查.(在类里以前创建好实例,用private修饰构造方法). 效果就跟 final , @Override一样.
饿汉模式
饿汉模式代码实现,就只需要读取数据,多线程读,是线程安全的操作. (代码如下: )
class Singleton { //现在类的内部获得实例 private static Singleton instance = new Singleton(); // 后续如果想使用这个类的实例, 都通过 getInstance 方法来获取. public static Singleton getInstance() { return instance; } // 设置程私有的构造方法 private Singleton() { }}
懒汉模式
相对于饿汉模式,就更加灵活,非必要不创建,减少了一些工作量,提高效率.但是,有收益的同时,肯定还会有风险 ,懒汉模式,既有读,也有写,就会涉及到线程不安全问题.
1.加锁. 这锁要加到什么位置合适.(涉及到修改操作只是在第一次实例化的时候会进行修改,后面都是读操作).
2.双重if,减少加锁次数.
3.解决指定重排序问题.
new 操作会涉及到指令重排序. new操作可以分为三步:
1) 申请内存空间
2)在内存空间构造对象
3) 把内存地址,赋值给引用
上诉三步,1)一定是先执行的, 哪种顺序对于单线程是没有影响的.
而对于多线程就会出问题,当线程t1 按照 1) 3) 2)顺序执行,就可能会出现2)还没执行完的时候也,另一个线程t2,已经开始执行,instance == null 就会不成立,t2线程就拿到另一个非法对象.
class SingletonLazy { // 3.解决指定重排序 问题 private static volatile SingletonLazy instance = null; public static SingletonLazy getInstance() { // 2.双重if if (instance == null) { //1. synchronized (SingletonLazy.class) { if (instance == null) { instance = new SingletonLazy(); } } } return instance; } private SingletonLazy() { }}
阻塞队列
是多线程代码中比较常用的一种数据结构. 也是一种特殊的队列.
1.线程安全
2.带有阻塞特性
a)如果队列为空,继续出队列,就会阻塞等待,阻塞到其它线程往对列里添加元素
b)如果队列为满,继续入队列,也会发生阻塞等待,阻塞到其它线程从队列中取走元素为止.
阻塞队列的最大意义,就是可以用来实现"生产者-消费者模型".
生产者-消费者模型意义
1.解耦合
2.削峰填谷
class MyBlockingQueue { //队列大小 private String[] date = new String[500]; //队列头 private volatile int head = 0; //队列下一个元素的位置 private volatile int rear = 0 ; //队列个数 private volatile int usedSized = 0; //入队 public void put(String elem) throws InterruptedException { synchronized (this) { /* if (usedSized == date.length) { //队列满了 return; }*/ while (usedSized == date.length) { //队列满了 // return; // 如果是队列满, 继续插入元素, 就会阻塞 this.wait(); } date[rear] = elem; rear = (rear + 1) % date.length; usedSized++; this.notify(); } } //出队 public String take() throws InterruptedException { synchronized (this) { while (usedSized == 0) { //队列为空 // return null; this.wait(); } String ret = date[head]; head = (head + 1) % date.length; usedSized--; this.notify(); return ret; } }}public class Demo22 { public static void main(String[] args) { MyBlockingQueue queue = new MyBlockingQueue(); //消费者 Thread t1 = new Thread(() -> { while (true) { try { String ret = queue.take(); System.out.println("消费元素:"+ret); Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }); //生产者 Thread t2 = new Thread(() -> { int num = 1; while (true) { try { queue.put(num+""); System.out.println("生产元素"+num); num++; Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } }); t1.start(); t2.start(); }}
运行效果:
定时器
约定一个时间,时间到达之后,开始执行某个代码的逻辑. 定时器是非常常见的,尤其是在网络通信的时候.
在标准库里,也是有现成的定时器实现.
public static void main(String[] args) { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("执行定时器任务!"); } },5000); System.out.println("程序启动!"); }
运行效果: