本文主要内容:
(1)生产者与消费者模型
1.生产、消费者模型
public class House {
private ArrayList<String> list = new ArrayList<>();
//向集合中添加元素的方法
public void add(){
if(list.size()<20){
list.add("a");
}else {
return;
}
}
//从集合中取元素
public void get(){
if(list.size()>0){
list.remove(0);
}else {
return;
}
}
}
public class Producer extends Thread {
private House house;
public Producer(House house){
this.house = house;
}
public void run(){
while (true){
house.add();
System.out.println("生产者存入一件货物");
}
}
}
public class Customer extends Thread {
private House house;
public Customer(House house){
this.house = house;
}
public void run(){
while (true){
house.get();
System.out.println("消费者取出了一件货物");
}
}
}
public class TestMain {
public static void main(String[] args) {
House house = new House();
Producer p = new Producer(house);
Customer c1 = new Customer(house);
Customer c2 = new Customer(house);
Customer c3 = new Customer(house);
p.start();
c1.start();
c2.start();
c3.start();
}
}
//代码中return不是很好,应该让线程的不同状态来回切换
(1)通过以下代码,成功的演示了线程安全的问题,两个消费者同时访问同一个仓库对象,仓库内只有一个元素时,两个消费者并发访问,会有可能产生强夺资源的问题。
public class House {
private ArrayList<String> list = new ArrayList<>();
//向集合中添加元素的方法
public void add(){
if(list.size()<20){
list.add("a");
}else {
return;
}
}
//从集合中取元素
public void get(){
if(list.size()>0){
list.remove(0);
}else {
return;
}
}
}
public class Producer extends Thread {
private House house;
public Producer(House house){
this.house = house;
}
public void run(){
while (true){
house.add();
System.out.println("生产者存入一件货物");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Customer extends Thread {
private House house;
public Customer(House house){
this.house = house;
}
public void run(){
while (true){
house.get();
System.out.println("消费者取出了一件货物");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class TestMain {
public static void main(String[] args) {
House house = new House();
Producer p = new Producer(house);
Customer c1 = new Customer(house);
Customer c2 = new Customer(house);
Customer c3 = new Customer(house);
p.start();
c1.start();
c2.start();
c3.start();
}
}
//运行结果会报错
//java.lang.ArrayIndexOutOfBoundsException: -1
// at java.util.ArrayList.add(ArrayList.java:459)
// at com.xiancheng.House.add(House.java:14)
// at com.xiancheng.Producer.run(Producer.java:14)
//代码中return不是很好,应该让线程的不同状态来回切换
(2)解决以上的问题
public class House {
private ArrayList<String> list = new ArrayList<>();
//向集合中添加元素的方法
public void add(){
if(list.size()<20){
list.add("a");
}else {
try {
this.wait();//仓库调用wait(),不是仓库对象等待,而是调用仓库生产者线程进入等待状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//从集合中取元素
public void get(){
if(list.size()>0){
list.remove(0);
}else {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//Producer、Customer、TestMain的方法如上代码
//运行结果
Exception in thread "Thread-3" Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
消费者取出了一件货物
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.xiancheng.House.get(House.java:29)
at com.xiancheng.Customer.run(Customer.java:14)
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.xiancheng.House.get(House.java:29)
at com.xiancheng.Customer.run(Customer.java:14)
(2-1)对象.wait():不是当前的这个对象wait,而是访问这个对象的线程wait()
(2-2)上述代码会出现异常,是应为所有的线程都进入了等待状态,没有线程做事,所以需要将所有的线程唤醒,代码如下:
public class House {
private ArrayList<String> list = new ArrayList<>();
//向集合中添加元素的方法
public void add(){
if(list.size()<20){
list.add("a");
}else {
try {
this.notifyAll();
this.wait();//仓库调用wait(),不是仓库对象等待,而是调用仓库生产者线程进入等待状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//从集合中取元素
public void get(){
if(list.size()>0){
list.remove(0);
}else {
try {
this.notifyAll();
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//Producer、Customer、TestMain类如上
//运行结果
Exception in thread "Thread-3" Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
消费者取出了一件货物
at java.lang.Object.notifyAll(Native Method)
at com.xiancheng.House.get(House.java:30)
at com.xiancheng.Customer.run(Customer.java:14)
java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at com.xiancheng.House.get(House.java:30)
at com.xiancheng.Customer.run(Customer.java:14)