目录
多线程案例
单例模式
单例模式是一种设计模式。
写代码时有些常见场景,设计模式就是针对这些常见场景给出的解决方案。
饿汉模式
class Singleton{
//1.使用static创建一个实例,并且立即进行实例化
//这个instance对应的实例,就是该类的唯一实例
private static Singleton instance=new Singleton();
//2.为了防止程序员在其他地方不小心new这个singleton,就可以把构造方法设为private
private Singleton(){}
//3.提供一个方法,让外面的能够拿到唯一的实例
public static Singleton getInstance(){
return instance;
}
}
public class Demo19 {
public static void main(String[] args) {
Singleton instance=Singleton.getInstance();
}
}
懒汉模式【经典面试题】
那么懒汉模式怎样保证线程安全呢?
public static Singleton2 getInstance(){
//并不是代码中有synchronized就一定线程安全,synchronized加的位置也得正确
//使用类对象作为锁对象(类对象在一个程序中,只有唯一的一份,就能保障多个线程调用getInstance的时候就是针对同一个对象进行加锁的)
//如果这个条件成立,说明当前的单例模式未初始化,存在线程安全风险,就需要加锁
if(instance ==null){
synchronized (Singleton2.class){
if(instance==null){
instance= new Singleton2();
}
}
}
return instance;
}
最终的代码:
class Singleton2{
//1.懒汉模式就不是立即初始化实例
private static volatile Singleton2 instance=null;
//2.把构造方法设为private
private Singleton2(){}
//3.提供一个方法来获取到上述单例的实例
//只有当真正用到这个实例的时候,才会真正去创建这个实例
public static Singleton2 getInstance(){
//并不是代码中有synchronized就一定线程安全,synchronized加的位置也得正确
//使用类对象作为锁对象(类对象在一个程序中,只有唯一的一份,就能保障多个线程调用getInstance的时候就是针对同一个对象进行加锁的)
//如果这个条件成立,说明当前的单例模式未初始化,存在线程安全风险,就需要加锁
if(instance ==null){
synchronized (Singleton2.class){
if(instance==null){
instance= new Singleton2();
}
}
}
return instance;
}
}
public class Demo20 {
public static void main(String[] args) {
Singleton2 instance =Singleton2.getInstance();
}
}
阻塞队列
此时的阻塞队列就可以作为生产者消费者模型中的交易场所
java标准库中阻塞队列的用法
public class Demo21 {
public static void main(String[] args) throws InterruptedException {
BlockingDeque<String > queue=new LinkedBlockingDeque<>();
queue.put("hello");
String s=queue.take();
}
}
自己实现阻塞队列
class MyBlockingQueue{
//保存数据本体
private int[] data=new int[100];
//有效元素个数
private int size=0;
//队首下标
private int head=0;
//队尾下标
private int tail=0;
//专门的锁对象
private Object locker=new Object();
//入队
//对于put操作,阻塞条件是队列为满
public void put(int value) throws InterruptedException {
synchronized (locker){
if(size==data.length){
locker.wait();
}
data[tail]=value;
tail++;
if(tail >= data.length){
tail=0; // tail=tail % data.length
}
size++;
//如果入队列成功,则队列非空,于是就唤醒take中的阻塞等待
locker.notify();
}
}
//出队列
public Integer take() throws InterruptedException {
synchronized (locker){
if(size==0){
//如果队列为空,就返回一个一个非法值
// return null;
locker.wait();
}
int ret=data[head];
head++;
if(head >= data.length){
head=0;
}
size--;
//take 成功之后,就唤醒put中的等待
locker.notify();
return ret;
}
}
}
public class Demo22 {
private static MyBlockingQueue queue=new MyBlockingQueue();
public static void main(String[] args) {
//实现一个简单的生产者消费者模型
Thread producer=new Thread(() ->{
int num=0;
while(true){
try {
System.out.println("生产了:"+ num);
queue.put(num);
num++;
//当生产者生产的慢一些的时候,消费者就得跟着生产者的步伐走
//Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
producer.start();
Thread customer =new Thread(() ->{
while(true){
try {
int num=queue.take();
System.out.println("消费了:"+num);
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
customer.start();
}
}