心得4--线程同步通讯-生产者与销售者

1.  分析:(生产者-消费者问题是多线程同步处理的典型问题)

有一块生产者和消费者共享的有界缓冲区,生产者往缓冲区放入产品,消费者从缓冲区取走产品,这个过程可以无休止的执行,不能因缓冲区满生产者放不进产品而终止,也不能因缓冲区空消费者无产品可取而终止。

2.     解决生产者消费者问题的方法

一种是采用某种机制保持生产者和消费者之间的同步

一种是在生产者和消费者之间建立一个管道

线程的同步解决生产者-消费者问题

限制公共缓冲区不能被两个线程同时访问,需要使用互斥锁,即用synchronized来标识同步资源。但加了互斥锁以后有可能会造出死锁。这时需要wait()方法和notify()方法--当前线程被阻塞并释放该对象的互斥锁

3.   通过上面的分析,大致了解了一下思路,下面用代码案例解说一下:

packagecom.javaEE.code.put;

//资源类

class Res{

      String name;

      String sex;

      boolean b; //设置一个旗帜,用来判断运用wait()方法时是否释放资源,在这里声明的booleanjava系统默认为false

}

//模拟生产者,生成产品

class Inputimplements Runnable{

      private Res r;

      public Input(Res r) {

           this.r = r;

      }

      public void run() {

           int x = 0;

           while(true){

//运用线程同步来避免生成者还没生产消费者就来输出、生产者生产好多了消费者才来、输出产品混乱(比如此例中的姓名张三性别gril的劣质产品问题)问题隐患

                 synchronized(r){

                      if(r.b){  //这里为假暂不执行

                            try {

                                  r.wait();

                            } catch(InterruptedException e) {

                                  // TODOAuto-generated catch block

                                  e.printStackTrace();

                            }

                      }

                      if(x==0){

                            r.name = "张三";

                            r.sex = "";

                      }else{

                            r.name ="jane";

                            r.sex = "girl";                 

                      }

                      r.b = true;   //将旗帜设置为假

                      r.notify();   //发出通讯,通知消费者

                 }

                 x = (x+1)%2;

           }

          

      }

     

}

//模拟消费者,输出产品

class Outputimplements Runnable{

      private Res r;

      public Output(Res r) {

           this.r = r;

      }

      public void run() {

           while(true){

                 synchronized(r){

                      if(!r.b){

                            try {

                                  r.wait();

                            } catch(InterruptedException e) {

                                  // TODOAuto-generated catch block

                                  e.printStackTrace();

                            }   

                      }

                      System.out.println("生产产品名称:"+r.name+"......"+"生成产品类别:"+r.sex);

                      r.b = false;

                      r.notify();

                     

                 }

           }

      }   

}

public classThreadPut {

      public static void main(String[] args) {

           Res r = new Res();

           Input in = new Input(r);

           Output out = new Output(r);

           Thread t1 = new Thread(in);

           Thread t2 = new Thread(out);

           t1.start();

           t2.start();

      }

}

4.以上代码还可以优化,优化后的代码为:

   这里用的是同步线程的synchronized函数,而上面例子中用的是代码块。这里把同步线程的代码都放到了资源类中。

packagecom.javaEE.code.put;

class Res1{

      String name;

      String sex;

      boolean flag;

      public synchronized void set(Stringname,String sex){

           if(flag)

                 try {

                      wait();

                 } catch (InterruptedExceptione) {

                      // TODO Auto-generatedcatch block

                      e.printStackTrace();

            this.name = name;

            this.sex = sex;

            flag = true;

            notify();

           }

      }

      public synchronized void out(){

           if(!flag)

                 try {

                      wait();

                 } catch (InterruptedExceptione) {

                      // TODO Auto-generatedcatch block

                      e.printStackTrace();

                 }

           System.out.println("生产产品名称:"+name+"......"+"生成产品类别:"+sex);

           flag = false;

           notify();

           }

}

class Input1implements Runnable{

      private Res1 r;

      public Input1(Res1 r) {

           this.r = r;

      }

      public void run() {

           int x = 0;

           while(true){ 

                 /*这里不像前面的例子,用个限制次数的for循环来终止循环,这里如果用for循环迭代语句i++并没有执行

                就进入synchronized代码库中了,然后生产然后通知输出,通知完之后再次生产回到这里又重新开新了!*/

                      if(x==0){

                            r.set("张三", "");                    

                      }else{

                            r.set("jane","girl");               

                      }

                      x = (x+1)%2;

                 }        

           }

}

class Output1implements Runnable{

      private Res1 r;

      public Output1(Res1 r) {

           this.r = r;

      }

      public void run() {

           while(true){

              r.out();                    

                 }

           }

}

public classOptimizeThreadPut {

      public static void main(String[] args) {

           Res r = new Res();

           Input in = new Input(r);

           Output out = new Output(r);

           Thread t1 = new Thread(in);

           Thread t2 = new Thread(out);

           t1.start();

           t2.start();

      }

}

posted @ 2012-09-05 14:27  yangkai_keven  阅读(208)  评论(0编辑  收藏  举报