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

来源:互联网 发布:淘宝怎么直接联系客服 编辑:程序博客网 时间:2024/04/30 00:35

                                                

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

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

多线程通讯问题解析:

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

文字如下:

                                               调用了sleep、wait方法的时候
                            <----------临时阻塞<----------
                                    
          调用start方法         抢到了cpu的执行权          执行完毕任务
创建--------------> 可运行状态 ----------------->运行状态-------------->死亡
                              <----------------
                                 被抢夺了cpu的执行权  
图列如下:

        


线程通讯:一个线程完成自己的任务后告诉另一个线程执行他自己的任务。
下面我们来看看线程通讯问题实例-----生产者与消费者:
首先描述一个产品类。
  1. package cn.chen.runndom;
  2. //描述一个产品类。
  3. class Product {
  4. String name;//产品名
  5. double price;//产品价格
  6. boolean flag =false;//是否生产完标记,默认为false表示没有生产完,true已经生产完毕了。
  7. //无参的构造方法。
  8. public Product() {}
  9. public Product(String name, double price) {
  10. this.name = name;
  11. this.price = price;
  12. }
  13. }
然后描述一个生产者。
  1. package cn.chen.runndom;
  2. //描述一个生产者
  3. class Producer extends Thread{
  4. //在生产者类中维护一个产品
  5. Product p;
  6. //通过构造函数传递产品进来,保证与消费者是同一一个产品对象。
  7. public Producer(Product p) {
  8. this.p = p;
  9. }
  10. //多线程执行的代码。
  11. public void run(){
  12. int i = 0;//定义变量
  13. while(true){
  14. //同步代码块。
  15. synchronized (p) {
  16. if(!p.flag){
  17. if(i%2==0){
  18. p.name="苹果";
  19. p.price=5.5;
  20. }else{
  21. p.name="香蕉";
  22. p.price=1.5;
  23. }
  24. System.out.println("生产者已经生产了"+p.name+"价格是:"+p.price);
  25. //改变标记。让生产者先停止,等待消费完
  26. p.flag=true;
  27. //唤醒线程池中正在等待的线程
  28. p.notify();
  29. i++;
  30. }else{
  31. try {
  32. //线程进入线程池中等待被唤醒
  33. p.wait();
  34. } catch (InterruptedException e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. }
  39. }
  40. }
  41. }

描述一个消费者:
  1. package cn.chen.runndom;
  2. class Customer extends Thread{
  3. //消费者类维护了一个产品类
  4. Product p;
  5. //通过构造函数传递产品,保证与生产者是同一个产品对象
  6. public Customer(Product p) {
  7. this.p = p;
  8. }
  9. //消费者线程执行的任务
  10. public void run(){
  11. //线程同步代码块,解决价格错乱问题。
  12. synchronized (p) {
  13. while(true){
  14. if(p.flag){
  15. System.out.println("消费者消费了"+p.name+"价格是:"+p.price);
  16. p.flag=false;
  17. //唤醒线程池中等待的线程
  18. p.notify();
  19. }else{
  20. try {
  21. p.wait();//线程进入线程池等待被唤醒。
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. }
  28. }
  29. }
现在万事俱备,创建线程并开启。
  1. package cn.chen.runndom;
  2. public class mainTest {
  3. public static void main(String[] args) {
  4. //创建产品对象。
  5. Product product = new Product();
  6. //创建生产者线程对象。把产品对象通过构造方法传递
  7. Producer producer = new Producer(product);
  8. //创建消费者线程对象、把产品对象通过构造方法传递
  9. Customer customer = new Customer(product);
  10. //调用start方法开启线程。
  11. producer.start();
  12. customer.start();
  13. }
  14. }
 输出结果。



从输出结果可以看出,生产者每生产完一个产品,消费者就会消费一个产品。
线程通讯中:
               wait();线程等待,如果一个线程调用了该方法,那么该方法就会进入等待状态,必须要其他线程唤醒,才能重新进入可运行状态。
               notily();唤醒等待线程中的一个线程。
注意:这俩个方法都是上帝Object类中的方法。必须在同步代码块或者同步函数中调用。且必须使用锁对象调用
一个线程执行了wait方法的时候,那么该线程会进入一个以锁对象为标识符的一个线程池等待。
一个线程执行了notify方法的时候,会唤醒线程池中等待线程的其中一个线程,    
注意:执行wait方法的时候是会释放锁对象,线程执行sleep方法的时候不会释放锁对象。所以要使用wait方法。

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


0 0
原创粉丝点击