volatile 修饰的变量, 能够保证 “内存可见性”
上述过程的完整代码如下:
public class Demo14 {//使用locker对象负责加锁,wait,notifyprivate static Object locker=new Object();public static void main(String[] args) {Thread t1=new Thread(() ->{while(true){synchronized (locker){System.out.println("t1 wait开始");try {locker.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1 wait结束");}}});t1.start();Thread t2=new Thread(() ->{while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (locker){System.out.println("t2 notify开始");locker.notify();System.out.println("t2 notify结束");}}});t2.start();}
}
其中,我们观察到notify的开始和结束的过程是非常快的
下面介绍代码案例
****
饿汉模式
懒汉模式
类加载的时候不创建实例. 第一次使用的时候才创建实例.
因为只有使用getInstance的时候,才会new出来一个对象;而在饿汉模式下,instance被当做一个类的属性,在类的加载的时候就被创建了。
上述过程的完整代码如下:
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;//生产者消费者模型
public class Demo18 {public static void main(String[] args) {//建一个阻塞队列,作为交易场所BlockingDeque<Integer> queue=new LinkedBlockingDeque<>();//一个线程负责生产Thread t1=new Thread(() ->{int count=0;while(true){try {queue.put(count);System.out.println("生产的元素为:"+count);count++;Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});//一个线程负责消耗Thread t2=new Thread(() ->{while(true){try {Integer n=queue.take();System.out.println("消耗的元素为:"+n);} catch (InterruptedException e) {e.printStackTrace();}}});t1.start();t2.start();}
}
阻塞队列的模拟实现
下面首先实现一般的队列
上述过程的代码如下:
class MyBlockingQueue{//使用循环队列来表示这个阻塞队列private String[] items=new String[1000];//队列的头部int head=0;//tail:队列的尾部的下一个元素. 总的来说, 队列中有效元素的范围 [head, tail)// 当 head 和 tail 相等(重合), 相当于空的队列.int tail=0;//size表示队列当前的元素个数int size=0;public void put(String elem){if(size>=items.length){//队列满return;}items[tail]=elem;tail++;if(tail>= items.length){tail=0;}size++;}public String take(){if(size==0){return null;}String elem=items[head];head++;if(head>= items.length){head=0;}size--;return elem;}
}
public class Demo19 {public static void main(String[] args) {MyBlockingQueue queue=new MyBlockingQueue();queue.put("aaa");queue.put("bbb");queue.put("ccc");queue.put("ddd");String elem= queue.take();System.out.println("elem="+elem);elem= queue.take();System.out.println("elem="+elem);elem= queue.take();System.out.println("elem="+elem);}
}
考虑线程安全性
实现阻塞
上述实现过程的最终代码如下:
class MyBlockingQueue{//使用循环队列来表示这个阻塞队列private String[] items=new String[10];//队列的头部volatile int head=0;//tail:队列的尾部的下一个元素. 总的来说, 队列中有效元素的范围 [head, tail)// 当 head 和 tail 相等(重合), 相当于空的队列.volatile int tail=0;//size表示队列当前的元素个数volatile int size=0;public void put(String elem) throws InterruptedException {synchronized (this){while(size>=items.length){//队列满//return;this.wait();}items[tail]=elem;tail++;if(tail>= items.length){tail=0;}size++;this.notify();}}public String take() throws InterruptedException {synchronized (this){while(size==0){// return null;this.wait();}String elem=items[head];head++;if(head>= items.length){head=0;}size--;this.notify();return elem;}}
}
public class Demo19 {public static void main(String[] args) {
/* MyBlockingQueue queue=new MyBlockingQueue();queue.put("aaa");queue.put("bbb");queue.put("ccc");queue.put("ddd");String elem= queue.take();System.out.println("elem="+elem);elem= queue.take();System.out.println("elem="+elem);elem= queue.take();System.out.println("elem="+elem);*///创建两个线程,表示生产者和消费者MyBlockingQueue queue=new MyBlockingQueue();Thread t1=new Thread(() ->{int count=0;while (true){try {queue.put(count + "");} catch (InterruptedException e) {e.printStackTrace();}System.out.println("生产"+count);count++;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});Thread t2=new Thread(() ->{while (true){String elem= null;try {elem = queue.take();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("消耗"+elem);try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}});t1.start();t2.start();}
}