之前的内容:理解多线程。创建多线程。多线程的安全问题/分析与理解。安全问题的解决办法/锁
———————————多线程的提高 线程之间的通信—————————————
之前的例子都是多个线程执行一个线程任务,多线程的提高——多个线程执行不同的线程任务,并发执行
例如:消费者与生产者,一个消费一个生产,执行的线程任务不同,但是处理的资源是一样的。但是要求同时进行
这叫做线程间的通信——你有你的动作,我有我的动作,但是处理的是同一个资源
初步代码:(执行有错误)
package Thread;
/*
线程的提升;生产者消费者问题
一个消费一个生产,执行的线程任务不同,但是处理的资源是一样的。但是要求同时进行
//线程间的通信
简化后的生产者和消费者——生产一个 消费一个
1.描述资源
2.描述生产者,具备自己的任务
3.描述消费者,具备自己的任务
*/
//描述资源——属性:名字,编号。行为:对商品名称赋值,获取商品
class Resource{//简化程序-设资源只有一个
private String name;
private int number=1;
//提供设置方法
public void set(String name ){
//给成员变量赋值
this.name = name+number;
number++;
//打印生产了那个商品
System.out.println(Thread.currentThread().getName()+" 生产者 "+this.name);
}
//消费者的
public void Out(){
System.out.println(Thread.currentThread().getName()+" 消费者 "+this.name);
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
r.set("面包");
}
}
//描述消费者
class consumer implements Runnable{
private Resource r;
consumer(Resource r){
this.r=r;
}
public void run(){
r.Out();
}
}
public class producerAndConsumer {
public static void main(String[] args){
//创建资源对象
Resource r = new Resource();
//创建线程任务
Producer pro = new Producer(r);
consumer con = new consumer(r);
//创建线程
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
t1.start();
t2.start();
}
}
运行结果:有错误
加上一个小循环:
问题:这个程序的输出必须遵守,生产一个消费一个,正确的数据应该为:1 1 2 2 3 3 4 4 5 5.
————————————————解决问题/分析问题—————————————
以上两种错误情况是其中的两种,现在针对相应的错误做出解决方案:
1.很早被生产的商品(编号已经)被覆盖,才被消费到
输出结果:1 2 3 4 5 6(生产者)//1 .。。。(消费者)
按理说编号1 早已经被覆盖,不应该现在才被消费到
解决办法《这是线程的安全问题——使用同步 ——————解决了该问题
2.问题1 解决,但是又出现新的问题:有些商品不会被消费到(连续生产但是没有消费/对同一个商品进行多次消费):1 2 3 4 5 //(生产者)5 5 5 5//(消费者)
我们的希望应该是:生产一个消费一个
思考:什么时候生产————————盘子里没有商品时
什么时候消费————————————盘子里有商品时
设置标记
思路
正确的代码:
package Thread;
/*
线程的提升;生产者消费者问题
一个消费一个生产,执行的线程任务不同,但是处理的资源是一样的。但是要求同时进行
//线程间的通信
简化后的生产者和消费者——生产一个 消费一个
1.描述资源
2.描述生产者,具备自己的任务
3.描述消费者,具备自己的任务
*/
//描述资源——属性:名字,编号。行为:对商品名称赋值,获取商品
class Resource{//简化程序-设资源只有一个
private String name;
private int number=1;
private boolean flag;
//提供设置方法
public synchronized void set(String name ){
if(flag){//先判断
try{wait();}catch(InterruptedException e){}//存在商品,此线程停止
}
else {
//给成员变量赋值
this.name = name + number;
number++;
//打印生产了那个商品
System.out.println(Thread.currentThread().getName() + " 生产者 " + this.name);
flag = true;//生产完,修改标志
notify();//唤醒消费者
}
}
//消费者的
public synchronized void Out(){
if(!flag){//先判断
try{wait();}catch(InterruptedException e){} //没有商品,消费者停止
}
System.out.println(Thread.currentThread().getName()+" 消费者 "+this.name);
flag =false;//修改标记
notify();//唤醒生产者
}
}
//描述生产者
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
for(int x=0;x<5;x++) {
r.set("面包");
}
}
}
//描述消费者
class consumer implements Runnable{
private Resource r;
consumer(Resource r){
this.r=r;
}
public void run(){
for(int x=0;x<5;x++) {
r.Out();
}
}
}
public class producerAndConsumer {
public static void main(String[] args){
//创建资源对象
Resource r = new Resource();
//创建线程任务
Producer pro = new Producer(r);
consumer con = new consumer(r);
//创建线程
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
t1.start();
t2.start();
}
}