您的位置:首页 > 职场人生

黑马程序员_2_多线程之生产者与消费者

2014-08-01 18:09 232 查看
黑马程序员_2_多线程之生产者与消费者

 -------
android培训、java培训、期待与您交流! ----------

多线程通讯问题解析:

我们要了解生产者与消费者问题,首先要明白,多线程执行的流程即生命周期。

文字如下:

调用了sleep、wait方法的时候
<----------临时阻塞<----------

调用start方法 抢到了cpu的执行权 执行完毕任务
创建--------------> 可运行状态 ----------------->运行状态-------------->死亡
<----------------
被抢夺了cpu的执行权

图列如下:



线程通讯:一个线程完成自己的任务后告诉另一个线程执行他自己的任务。

下面我们来看看线程通讯问题实例-----生产者与消费者:

首先描述一个产品类。

package cn.chen.runndom;

//描述一个产品类。

class Product {

String name;//产品名

double price;//产品价格

boolean flag =false;//是否生产完标记,默认为false表示没有生产完,true已经生产完毕了。

//无参的构造方法。

public Product() {}


public Product(String name, double price) {

this.name = name;

this.price = price;

}

}

[/code]

然后描述一个生产者。

package cn.chen.runndom;

//描述一个生产者

class Producer extends Thread{

//在生产者类中维护一个产品

Product p;

//通过构造函数传递产品进来,保证与消费者是同一一个产品对象。

public Producer(Product p) {

this.p = p;

}

//多线程执行的代码。

public void run(){

int i = 0;//定义变量

while(true){

//同步代码块。

synchronized (p) {

if(!p.flag){

if(i%2==0){

p.name="苹果";

p.price=5.5;

}else{

p.name="香蕉";

p.price=1.5;

}

System.out.println("生产者已经生产了"+p.name+"价格是:"+p.price);

//改变标记。让生产者先停止,等待消费完

p.flag=true;

//唤醒线程池中正在等待的线程

p.notify();

i++;

}else{

try {

//线程进入线程池中等待被唤醒

p.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

}

[/code]

描述一个消费者:

package cn.chen.runndom;

class Customer extends Thread{

//消费者类维护了一个产品类

Product p;

//通过构造函数传递产品,保证与生产者是同一个产品对象

public Customer(Product p) {

this.p = p;

}


//消费者线程执行的任务

public void run(){

//线程同步代码块,解决价格错乱问题。

synchronized (p) {

	while(true){

if(p.flag){

System.out.println("消费者消费了"+p.name+"价格是:"+p.price);

p.flag=false;

//唤醒线程池中等待的线程

p.notify();

}else{

try {

p.wait();//线程进入线程池等待被唤醒。

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

}

[/code]

现在万事俱备,创建线程并开启。

package cn.chen.runndom;


public class mainTest {

public static void main(String[] args) {

//创建产品对象。

Product product = new Product();

//创建生产者线程对象。把产品对象通过构造方法传递

Producer producer = new Producer(product);

//创建消费者线程对象、把产品对象通过构造方法传递

Customer customer = new Customer(product);

//调用start方法开启线程。

producer.start();

customer.start();

}

}

[/code]

输出结果。




从输出结果可以看出,生产者每生产完一个产品,消费者就会消费一个产品。

线程通讯中:

wait();线程等待,如果一个线程调用了该方法,那么该方法就会进入等待状态,必须要其他线程唤醒,才能重新进入可运行状态。

notily();唤醒等待线程中的一个线程。

注意:这俩个方法都是上帝Object类中的方法。必须在同步代码块或者同步函数中调用。且必须使用锁对象调用。

一个线程执行了wait方法的时候,那么该线程会进入一个以锁对象为标识符的一个线程池等待。
一个线程执行了notify方法的时候,会唤醒线程池中等待线程的其中一个线程,
注意:执行wait方法的时候是会释放锁对象,线程执行sleep方法的时候不会释放锁对象。所以要使用wait方法。

  -------android培训java培训、期待与您交流!
----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: