Java 各种设计模式 持续更新

一、生产者和消费者模式

关于Object类中的wait和notify方法。(生产者和消费者模式!)

第一:wait和notify方法不是线程对象的方法,是java中任何一个java对象

	都有的方法,因为这两个方式是Object类中自带的。
		wait方法和notify方法不是通过线程对象调用,
		不是这样的:t.wait(),也不是这样的:t.notify()..不对。

第二:wait()方法作用?

		Object o = new Object();
		o.wait();

		表示:
			让正在o对象上活动的线程进入等待状态,无期限等待,
			直到被唤醒为止。
			o.wait();方法的调用,会让“当前线程(正在o对象上
			活动的线程)”进入等待状态。

第三:notify()方法作用?

		Object o = new Object();
		o.notify();

		表示:
			唤醒正在o对象上等待的线程。
		
		还有一个notifyAll()方法:
			这个方法是唤醒o对象上处于等待的所有线程。

概念

  • 1、使用wait方法和notify方法实现生产者和消费者模式
  • 2、什么是生产者和消费者模式?
  • 生产线程负责生产,消费现场负责消费。
  • 生成线程和消费线程要达到均衡。
  • 这是一种特殊的业务需求,在这种特殊的情况下需要使用wait方法和noify方法
  • 3、wait和notify方法不是线程对象的方法,是普通java对象都有的方法。
  • 4、wait和notify方法建立在线程同步的基础上。因为多线程要同时操作一个仓库,有线程安全问题。
  • 5、wait方法作用:o.wait让正在o对象上活动的线程t进入等待状态,并且释放掉t线程之前占有的o对象的锁。
  • 6、notify方法作用:o.notify()让正在o对象上等待的线程唤醒,只是通知,不会释放o对象上之前占有的锁。
  • 7、模拟仓库使用list集合,假设只能存在一个。

代码示例

这里notifyall和notify都可以,比如消费者刚唤醒生产者,即使消费者又抢到了这把锁,但是会判断仓库里是否有库存,没有的话还是会进入wait。

public class ThreadTest16 {
    public static void main(String[] args) {
        List list  = new ArrayList();

        //创建两个线程对象
        Thread t1 = new Thread(new Producer(list));

        Thread t2 = new Thread(new Consumer(list));

        t1.setName("生产者线程");
        t2.setName("消费者线程");
        t1.start();
        t2.start();
    }
}


//生产者
class Producer implements Runnable{

    //仓库
    private List list;

    public Producer(List list) {
        this.list = list;
    }

    @Override
    public void run() {
        //使用死循环模拟一直生产
        while (true){
            //给仓库list对象加锁
            synchronized (list){
                if (list.size()>0){//大于0,说明有1个元素了
                    try {
                        list.wait();//进入等待,释放锁
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                Object obj = new Object();
                list.add(obj);
                System.out.println(Thread.currentThread().getName() + "--->" + obj);
                //唤醒消费者进行消费
                list.notifyAll();
            }


        }
    }
}

//消费者
class Consumer implements Runnable{

    private List list;

    public Consumer(List list) {
        this.list = list;
    }

    @Override
    public void run() {
        //一直消费
        while (true){
            synchronized (list){
                if (list.size()==0){
                    try {
                        //仓库已经空了。
                        //消费者线程等待,释放list锁
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //消费者进行消费
                Object obj = list.remove(0);
                System.out.println(Thread.currentThread().getName() + "--->" + obj);
                //唤醒生产者进行生产
                list.notifyAll();
            }

        }
    }
}

二、单例模式

饿汉式

  • (1)构造器私有化
  • (2)自行创建,并且用静态变量保存
  • (3)向外提供这个实例
  • (4)强调这是一个单例,我们可以用final修改
    直接创建(记住这个)
    /*
    饿汉式:
    直接创建实例对象,不管你是否需要这个对象

*1)构造器私有化
*2)自行创建,并且用静态变量保存
*3)向外提供这个实例
*4)强调这是一个单例,我们可以用final修改
* */
public class Singleton1 {
    //习惯上把常量写为大写
    private static final Singleton1 INSTANCE = new Singleton1();

    private Singleton1() {

    }
public static Singleton1 getInstance(){
    return INSTANCE;
    }


}

枚举式
/*

  • 枚举类型:表示该类型的对象是有限的几个
  • 我们可以限定为一个,就成了单例
  • 枚举类型构造器都是私有化的
  • */
    public enum Singleton2 {
    INSTANCE

}
静态代码块

public class Singleton3 {
    public static final Singleton3 INSTANCE;

    static {
        INSTANCE = new Singleton3();
    }

    private Singleton3() {
    }
}

懒汉式
线程不安全模式(单线程)

public class Singleton4 {
    private Singleton4(){

    }
    private static Singleton4 instance;
    public static Singleton4 getInstance(){
        if(instance == null){
            instance = new Singleton4();
        }
        return instance;
    }
}

多线程安全模式
为什么要两次判断:第一次判断:解决只有在单例没有创建时才存在线程安全问题,所以只在此时加锁。第二次判断:第一个线程进来,第二个线程等待,第一个线程创建完了,第二个不判断就又创建一次。

public class Singleton6 {
    // volatile保证每次使用时,都从主存中取
    private static volatile Singleton6 instance;
    // 私有化构造函数
    private Singleton6() {}
    // 提供其他类获取实例的静态方法
    public static Singleton6 getInstance() {
        if (instance == null) {
            // 如果实例不存在,进入同步代码块
            synchronized (Singleton6.class) {
                if (instance == null) {
                    // 如果实例在代码块中仍不存在,创建实例
                    instance = new Singleton6();
                }
            }
        }
        return instance;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值