线程之生产消费者模式

package com.uncle.testthread.producer;

/**
 * 生产消费者模型
 * 	1.通过这个模型  成功的演示出了  线程安全的问题
 * 		两个消费者  同时访问同一个仓库对象   仓库内只有一个元素的时候
 * 		两个消费者并发访问  会有可能产生抢夺资源的问题
 * 	2.自己解决一下线程安全的问题
 * 		让仓库对象被线程访问的时候   仓库对象被锁定
 * 		仓库对象只能被一个线程访问   其他的线程处于等待状态
 * 		特征修饰符
 * 		synchronized  同步  一个时间点只有一个线程访问
 * 		线程安全锁
 * 		两种形式写法
 * 		1.将synchronized关键字 放在方法的结构上
 * 		   public synchronized void get(){}
 * 		   锁定的是调用方法时的那个对象
 * 		2.将synchronized关键字 方在方法(构造方法 块)的内部
 * 		   public void get(){
 * 			好多代码
 * 			synchronized(对象){
 * 				好多代码
 *                        }
 * 			好多代码
 *           }
 * 	3.我们觉得return不是很好
 * 		应该让线程的不同状态来回切换
 * 		执行   等待   执行   等待
 * 		wait()	Object类中的方法
 * 		notify  notifyAll   Object类中的方法
 *
 * 		sleep();
 * 		run();
 * 		start();
 * 	 4.通过上述的生产消费者模型
 * 		做一个非常完整而且安全的模型
 * 		1.利用线程安全锁    特征修饰符synchronized 
 * 			两种不同的写法
 * 			不管怎么写   锁定的永远是对象
 * 		2.利用方法控制线程状态的来回切换
 * 			wait
 * 			notify	notifyAll
 * 			上述三个方法都是Object类中的方法
 * 		3.Thread类中的方法
 * 			sleep方法    静态方法(参数long 毫秒值)
 * 			setPriority(10);	getPriority();
 * 			设置/获取线程的优先级  1-10  
 * 			数字越高优先级越高   更加容易获取CPU分配的资源碎片
 * 		4.笔试题
 * 			程序 进程 线程 概念的区别
 * 			线程的创建方式
 * 			线程的几种状态  如何切换
 * 				sleep方法   wait方法的区别
 * 			1.类	Thread类	  Object类
 * 			2.调用	静态 类名.   对象.
 * 			3.理解	哪个位置调用   对象调用方法
 * 				哪个线程等待   访问对象的其他线程等待
 * 			4.唤醒	不需要别人      需要其他对象调用notify唤醒
 * 			5.锁	不会释放锁      等待后会释放锁	
 */
public class TestMain {

    public static void main(String[] args){
        Warehouse house = new Warehouse();//里面有一个ArrayList线程非安全
        Producer p = new Producer(house);
        //设置线程的优先级别1-10
        p.setPriority(10);

        Consumer c1 = new Consumer(house);
        Consumer c2 = new Consumer(house);
        p.start();
        c1.start();
        c2.start();
    }
}

package com.uncle.testthread.producer;

public class Consumer extends Thread{

    //为了保证生产者 和消费者使用同一个仓库对象  添加一个属性
    private Warehouse house;
    public Consumer(Warehouse house){
        this.house=house;
    }

    //消费者的方法  一直从仓库内获取元素
    public void run(){
        while(true){
            house.get();
            System.out.println("消费者拿走了一件货物");
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

package com.uncle.testthread.producer;

public class Producer extends Thread {

    //为了保证生产者 和消费者使用同一个仓库对象  添加一个属性
    private Warehouse house;
    public Producer(Warehouse house){
        this.house=house;
    }

    //生产者的run方法  一直向仓库内添加元素
    public void run(){
        while(true){
            house.add();
            System.out.println("生产者存入了一件货物");
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

package com.uncle.testthread.producer;

import java.util.ArrayList;

public class Warehouse {

    //单例设计模式

    //仓库里面的集合  存放元素
    private ArrayList<String> list = new ArrayList<>();
    //向集合内添加元素的方法
    public synchronized void add(){
        if(list.size()<20) {
            list.add("a");
        }else{
            //return;//让方法执行到这里就结束方法
            try {
                this.notifyAll();
                this.wait();//仓库调用wait 不是仓库对象等待  访问仓库的生产者线程进入等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //从集合内获取元素的方法
    public synchronized void get(){
        if(list.size()>0) {
            list.remove(0);//集合越界的问题
        }else{
            //return;
            try {
                this.notifyAll();
                this.wait();//仓库对象调用wait  不是仓库对象等待  访问仓库的消费者线程进入等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

  • 多线程并发 可能会产生线程安全 抢资源问题
    在这里插入图片描述
  • 线程对象改变产生的异常
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值