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();
}
}
}
}
- 多线程并发 可能会产生线程安全 抢资源问题
- 线程对象改变产生的异常