这里主要是防止线程死锁的问题,也就是本身和竞争者之间都存在一个共享资源,例如生产者和消费者都在争抢同一个仓库的娃娃,生产者生产了娃娃,消费者才能去消费娃娃,就是这样的协同原理,这里主要涉及到的是三个函数,分别是Wait(),notify(),synchronized。
第一种策略是利用缓冲区法,建立一个缓冲区,让生产者和消费者都去缓冲区去拿资源,再缓冲区使用同步块防止出现错误。缓冲区的作用主要有如下几个作用。
对于生产者而言:
1、要确保在仓库放满的情况下不能再继续往仓库存放东西,防止溢出操作,如果满了就要wait等待,直到消费者消费后在重新开启。
2、确保可以在未满的时候可以放入。
对于消费者而言:
消费者主要是消费产品,防止在0的时候消费了产品产生负数就可以了。
package TestSleep;
//测试生产者消费者模型——>利用缓冲区
public class TestCP {
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Productor(container).start();
new Consumer(container).start();
}
}
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("生产了"+i+"鸡");
container.push(new Chincken(i));
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了-> "+container.pop().number+"鸡");
}
}
}
//产品
class Chincken{
int number;
public Chincken(int number){
this.number = number;
}
}
//缓冲区
class SynContainer {
Chincken[] chinckens = new Chincken[10];
int count = 0;
public synchronized void push(Chincken chincken){
//如果容器满了
if(count == chinckens.length){
try{
this.wait();}
catch (InterruptedException e){
e.printStackTrace();
}
}
chinckens[count] = chincken;
count++;
//如果容器没有满,放入
this.notifyAll();
}
//消费者消费产品
public synchronized Chincken pop(){
//判断能否消费
if(count == 0){
//等待生产者
try{
this.wait();}
catch (InterruptedException e){
e.printStackTrace();
}
}
count--;
Chincken chincken = chinckens[count];
this.notifyAll();
//吃完了生产
return chincken;
}
}
2、信号灯法也就是标志位法(flag)
这里不在运用缓冲区来限制线程之间的协作关系,而是通过设置标志位的方法来表示线程的等待和停止,具体代码如图下所示。
package TestSleep;
import java.sql.SQLOutput;
public class TestCP2 {
public static void main(String[] args) {
TV tv = new TV();
new player(tv).start();
new watcher(tv).start();
}
}
class player extends Thread{
TV tv;
public player(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(i%2==0){
this.tv.play("快乐大本营");
}else{
this.tv.play("抖音,记录美好生活!");
}
}
}
}
class watcher extends Thread{
TV tv;
public watcher(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
tv.watch();
}
}
}
class TV {
//演员表演,观众等待
//观众观看,演员等待
String voice;//表演的节目
boolean flag = true;
//表演
public synchronized void play(String voice){
if(!flag){
try{
this.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("演员表演"+voice);
//通知观看
this.notifyAll();
this.voice = voice;
this.flag = !this.flag;
}
//观看
public synchronized void watch(){
if(flag){
try{
this.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("观看了"+voice);
//通知表演
this.notifyAll();
this.flag = !this.flag;
}
}