黑马程序员---java基础------------------多线程通信

线程间通讯:其实就是多个线程在操作同一个资源,但是操作的动作不同。

class Res {  

    private String name;  

    private String sex;  

    private  boolean flag = false;

    public synchronized void set(String name,String sex)

    {

        if(r.flag)     

          try{r.wait();}catch(Exception e){}    

        this.name = name;

        this.sex = sex;

        flag = true;    

        this.notify();   

    }

     public synchronized void out()  

    {

        if(r.flag)    

          try{r.wait();}catch(Exception e){}   

        System.out.println(name+"........"+sex);

        flag = false;   

        this.notify();  

     }

}

class Input implements Runnable {  

    private Res r ;  

    Input(Res r)  {   

        this.r = r;  

    }  

    public void run()  {   

        int x = 0;   

        while(true)   {    

           if(x==0)          

              r.set("mike","man");     

           else    

              r.set("丽丽","女女女女女");     

           x = (x+1)%2;     

        }  

    }

}

class Output implements Runnable {  

      private Res r ;    

      Output(Res r)  {   

          this.r = r;  

      }  

      public void run()  {   

          while(true)   {    

              r.out();

          }  

      }

}

class  InputOutputDemo {  

      public static void main(String[] args)  {   

            Res r = new Res();

             new Thread(new Input(r)).start();

             new Thread(new Output(r)).start(); 

      }

}

 wait();     notify();     notifyAll();都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。

    为什么这些操作线程的方法要定义Object类中呢?因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,只有同一个锁上的被等待线程,可以

      被同一个锁notify唤醒。不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定

      义Object类中。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

生产者和消费者的例子

    对于多个生产者和消费者。为什么要定义while判断标记。原因:让被唤醒的线程再一次判断标记。

    为什么定义notifyAll,因为需要唤醒对方线程。因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

class ProducerConsumerDemo {  

     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(pro);   

        Thread t3 = new Thread(con);   

        Thread t4 = new Thread(con);

            t1.start();   

        t2.start();   

        t3.start();   

        t4.start();

     }

}

class Resource {  

    private String name;  

    private int count = 1;  

    private boolean flag = false;    

    public synchronized void set(String name)  {   

        while(flag)    

            try{this.wait();}catch(Exception e){}

        //t1(放弃资格)  t2(获取资格)   

        this.name = name+"--"+count++;

          System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);   

         flag = true;  

          this.notifyAll();  

    }

    public synchronized void out()
     {
          while(!flag)
             try{wait();}catch(Exception e){}

           //t3(放弃资格) t4(放弃资格)
         System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
         flag = false;
         this.notifyAll();
     }

}

class Producer implements Runnable {  

     private Resource res;

     Producer(Resource res)  {   

        this.res = res;  

    }  

    public void run()  {   

        while(true)   {    

            res.set("+商品+");   

        }  

    }

}

class Consumer implements Runnable {  

    private Resource res;

     Consumer(Resource res)  {   

        this.res = res;  

    }  

    public void run()  {   

        while(true)   {    

            res.out();   

        }  

    }

}

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

import java.util.concurrent.locks.*;

class ProducerConsumerDemo2 {  

    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(pro);   

        Thread t3 = new Thread(con);   

        Thread t4 = new Thread(con);

           t1.start();   

        t2.start();   

        t3.start();   

        t4.start();

     }

}

class Resource {  

      private String name;  

      private int count = 1;  

      private boolean flag = false;    

      //  t1    t2  

      private Lock lock = new ReentrantLock();

        private Condition condition_pro = lock.newCondition();  

      private Condition condition_con = lock.newCondition();

       public  void set(String name)throws InterruptedException  {   

          lock.lock();   

          try   {    

              while(flag)     

              condition_pro.await();              1.5新特性:通过指定就可以针对值让己方等待,代替了wait();

              //t1,t2    

              this.name = name+"--"+count++;

                  System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);    

              flag = true;    

              condition_con.signal();   //通过指定就可以避免唤醒的时候吧己方唤醒,这也就不用signalALL(); 和notifyAll();(已经被替代)

          }   

          finally   {    

              lock.unlock();//释放锁的动作一定要执行。   

          }  

      }

       //  t3   t4   

      public  void out()throws InterruptedException  {   

          lock.lock();   

          try   {    

            while(!flag)     

            condition_con.await();    1.5新特性:通过指定就可以针对值让己方等待,代替了wait();

            System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);    

            flag = false;    

            condition_pro.signal();   //通过指定就可以避免唤醒的时候吧己方唤醒,这也就不用signalALL(); 和notifyAll();(已经被替代)

          }   

          finally   {    

            lock.unlock();   

          }     

      }

}

class Producer implements Runnable {  

      private Resource res;

        Producer(Resource res)  {   

          this.res = res;  

      }  

      public void run()  {   

          while(true)   {    

             try    {     

                res.set("+商品+");    

             }    catch (InterruptedException e)    {    }       

          }  

      }

}

class Consumer implements Runnable {  

      private Resource res;

        Consumer(Resource res)  {   

          this.res = res;  

      }  

      public void run()  {   

          while(true)   {    

             try    {     

                res.out();      

             }    catch (InterruptedException e)    {    }   

          }  

      }

}

    JDK1.5 中提供了多线程升级解决方案。将同步Synchronized替换成现实Lock操作。将Object中的wait,notify notifyAll,替换了Condition对象。该对象可

        以Lock锁 进行获取。该示例中,实现了本方只唤醒对方操作。

停止线程

      如何停止线程?:只有一种,run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。

          特殊情况:当线程处于了冻结状态。就不会读取到标记。那么线程就不会结束。

          当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。Thread

        类提供该方法 interrupt();

 

class StopThread implements Runnable {  

      private boolean flag =true;  

      public synchronizede void run()  {   

          while(flag)   {        //将flag置为false就可以控制循环了

              try{

                  wait();

              }

              catch(InterruppedException e)

              {

                System.out.println(Thread.currentThread().getName()+"....Exception");   

                flag = false; //代替了下面的changeFlag();

              }

              System.out.println(Thread.currentThread().getName()+"....run");  

          }  

      }  

      public void changeFlag()  {   

          flag = false;  

      }

}

class  StopThreadDemo {  

      public static void main(String[] args)  {   

          StopThread st = new StopThread();      

          Thread t1 = new Thread(st);   

          Thread t2 = new Thread(st);

            t1.setDaemon(true);   //守护线程,要在线程前调用,只要前台线程一结束,守护线程就自动结束了,蓝色字体就去掉了没用了

          t2.setDaemon(true);   

          t1.start();   

          t2.start();

            int num = 0;

            while(true)   {    

              if(num++ == 60)    {     

                  st.changeFlag();     

                  //t1.interrupt();     //对冻结进行清除。强制让线程恢复到运行状态中来

                  //t2.interrupt();     

                  break;    

              }    

              System.out.println(Thread.currentThread().getName()+"......."+num);   

          }   

          System.out.println("over");  

      }

}

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

join: 当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。join可以用来临时加入线程执行。

class Demo implements Runnable {  

      public void run()  {   

          for(int x=0; x<70; x++)   {    

              System.out.println(Thread.currentThread().toString()+"....."+x);    

              Thread.yield();   

          }  

      }

}

class  JoinDemo {  

      public static void main(String[] args) throws Exception  {   

          Demo d = new Demo();   

          Thread t1 = new Thread(d);   

          Thread t2 = new Thread(d);   

          t1.start();      

          //t1.setPriority(Thread.MAX_PRIORITY);

           t2.start();

           //t1.join();

           for(int x=0; x<80; x++)   {    

              //System.out.println("main....."+x);   

           }   

           System.out.println("over");  

     }

}

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

class MyThread extends Thread{  

      public void run(){   

          try {    

            Thread.currentThread().sleep(3000);   

          } catch (InterruptedException e) {   }   

          System.out.println("MyThread running");  

      }

}

public class ThreadTest{  

      public static void main(String argv[]) {   

          MyThread t = new MyThread();   

          t.run();   

          t.start();   

          System.out.println("Thread Test");   

      }

}

代码分析过程:

MyThread t = new MyThread(); 创建了一个线程。

    t.run();

      调用MyThread对象的run方法。这是只有一个线程在运行就是主线程。当主线程执行到了run方法中的sleep(3000);时。这是主线程处于冻结状态。程序并没有任何

          执行。当3秒过后,主线程打印了  MyThread running。 run方法执行结束。

    t.start();

      开启了t线程。有两种可能情况。第一种,主线程在只执行了t.start()后,还具有执行权,继续往下执行,打印了Thread Test。主线程结束。t线程获取执行权,调用

          自己的run方法。然后执行的sleep(3000);冻结3秒。3秒后,打印MyThread running t线程结束,整个程序结束。

      第二种情况:主线程执行到t.start();开启了t线程,t线程就直接获取到了执行权。就调用自己的run方法。指定到sleep(3000).t线程冻结3秒,这是t线程就是释放了

   执行权。那么主线程开始执行打印了Thread Test,主线程结束。等到3秒后,t线程打印MyThread running ,然后t线程结束。程序结束。

 

posted @ 2013-05-25 19:10  zhao198627  阅读(117)  评论(0编辑  收藏  举报