zoukankan      html  css  js  c++  java
  • 线程之间的通信机制

    1.首先我们回顾一下面试题:

    两个线程,一个线程打印1-52,另一个打印字母A-Z打印顺序为12A34B...5152Z, 要求用线程间通信

    这个面试题就就是完全考察线程之间的通信机制,常用的技术分为二种

    1. 一种是Object 类中的自带的 wait 和 notify 机制,
    2. 二是 lock中的通信机制 Condition接口中的 await 和 signal 方法。

    线程间通信:1、生产者+消费者2、通知等待唤醒机制

    1. Object 类中的自带的 wait 和 notify 机制实现, synchronized用来办证线程安全
      package com.atguigu.thread;
       
      import java.util.concurrent.locks.Condition;
      import java.util.concurrent.locks.Lock;
      import java.util.concurrent.locks.ReentrantLock;
       
       
       
      class ShareDataOne//资源类
      {
        private int number = 0;//初始值为零的一个变量
       
        public synchronized void increment() throws InterruptedException 
        {
           //1判断
           if(number !=0 ) {
             this.wait();
           }
           //2干活
           ++number;
           System.out.println(Thread.currentThread().getName()+"	"+number);
           //3通知
           this.notifyAll();
        }
        
        public synchronized void decrement() throws InterruptedException 
        {
           // 1判断
           if (number == 0) {
             this.wait();
           }
           // 2干活
           --number;
           System.out.println(Thread.currentThread().getName() + "	" + number);
           // 3通知
           this.notifyAll();
        }
      }
       
      /**
       * 
       * @Description:
       *现在两个线程,
       * 可以操作初始值为零的一个变量,
       * 实现一个线程对该变量加1,一个线程对该变量减1,
       * 交替,来10轮。 
       * @author xialei
       *
       *  * 笔记:Java里面如何进行工程级别的多线程编写
       * 1 多线程变成模板(套路)-----上
       *     1.1  线程    操作    资源类  
       *     1.2  高内聚  低耦合
       * 2 多线程变成模板(套路)-----下
       *     2.1  判断
       *     2.2  干活
       *     2.3  通知
       
       */
      public class NotifyWaitDemoOne
      {
        public static void main(String[] args)
        {
           ShareDataOne sd = new ShareDataOne();
           new Thread(() -> {
             for (int i = 1; i < 10; i++) {
                try {
                  sd.increment();
                } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
                }
             }
           }, "A").start();
           new Thread(() -> {
             for (int i = 1; i < 10; i++) {
                try {
                  sd.decrement();
                } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
                }
             }
           }, "B").start();
        }
      }

      注意点:线程通信最好不要用 if 去判断,用 while 去判断,因为用 if 去判断容易造成虚假唤醒,以下是修改之后的数据

      package com.atguigu.thread;
       
      import java.util.concurrent.locks.Condition;
      import java.util.concurrent.locks.Lock;
      import java.util.concurrent.locks.ReentrantLock;
       
      import org.omg.IOP.Codec;
       
       
      class ShareData//资源类
      {
        private int number = 0;//初始值为零的一个变量
       
        public synchronized void increment() throws InterruptedException 
        {
           //判断
           while(number!=0) {
             this.wait();
           }
           //干活
           ++number;
           System.out.println(Thread.currentThread().getName()+" 	 "+number);
           //通知
           this.notifyAll();;
        }
        
        public synchronized void decrement() throws InterruptedException 
        {
           //判断
           while(number!=1) {
             this.wait();
           }
           //干活
           --number;
           System.out.println(Thread.currentThread().getName()+" 	 "+number);
           //通知
           this.notifyAll();
        }
      }
       
      /**
       * 
       * @Description:
       *现在两个线程,
       * 可以操作初始值为零的一个变量,
       * 实现一个线程对该变量加1,一个线程对该变量减1,
       * 交替,来10轮。 
       * @author xialei
       *
       *  * 笔记:Java里面如何进行工程级别的多线程编写
       * 1 多线程变成模板(套路)-----上
       *     1.1  线程    操作    资源类  
       *     1.2  高内聚  低耦合
       * 2 多线程变成模板(套路)-----下
       *     2.1  判断
       *     2.2  干活
       *     2.3  通知
       
       */
      public class NotifyWaitDemo
      {
        public static void main(String[] args)
        {
           ShareData sd = new ShareData();
           new Thread(() -> {
       
             for (int i = 1; i <= 10; i++) {
                try {
                  sd.increment();
                } catch (InterruptedException e) {
                  e.printStackTrace();
                }
             }
           }, "A").start();
           
           new Thread(() -> {
       
             for (int i = 1; i <= 10; i++) {
                try {
                  sd.decrement();
                } catch (InterruptedException e) {
                  e.printStackTrace();
                }
             }
           }, "B").start();
           new Thread(() -> {
       
             for (int i = 1; i <= 10; i++) {
                try {
                  sd.increment();
                } catch (InterruptedException e) {
                  e.printStackTrace();
                }
             }
           }, "C").start();
           new Thread(() -> {
       
             for (int i = 1; i <= 10; i++) {
                try {
                  sd.decrement();
                } catch (InterruptedException e) {
                  e.printStackTrace();
                }
             }
           }, "D").start();
           
        }
      }
       
       
       
       
       
      /*
       * * 
       * 2 多线程变成模板(套路)-----下
       *     2.1  判断
       *     2.2  干活
       *     2.3  通知
       * 3 防止虚假唤醒用while
       * 
       * 
       * */
       
       
       
       
       
       

          使用 Condition去做

    package com.atguigu.thread;
     
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
     
    import org.omg.IOP.Codec;
     
     
    class ShareData//资源类
    {
      private int number = 0;//初始值为零的一个变量
     
      private Lock lock = new ReentrantLock();
      private Condition condition  = lock.newCondition(); 
       
      public  void increment() throws InterruptedException 
      {
         
          lock.lock();
             try {
              //判断
              while(number!=0) {
                condition.await();
              }
              //干活
              ++number;
              System.out.println(Thread.currentThread().getName()+" 	 "+number);
              //通知
              condition.signalAll();
         } catch (Exception e) {
           e.printStackTrace();
         } finally {
           lock.unlock();
         }
         
      }
      
      
      public  void decrement() throws InterruptedException 
      {
          
          lock.lock();
             try {
              //判断
              while(number!=1) {
                condition.await();
              }
              //干活
              --number;
              System.out.println(Thread.currentThread().getName()+" 	 "+number);
              //通知
              condition.signalAll();
         } catch (Exception e) {
           e.printStackTrace();
         } finally {
           lock.unlock();
         }
         
      }
      
      /*public synchronized void increment() throws InterruptedException 
      {
         //判断
         while(number!=0) {
           this.wait();
         }
         //干活
         ++number;
         System.out.println(Thread.currentThread().getName()+" 	 "+number);
         //通知
         this.notifyAll();;
      }
      
      public synchronized void decrement() throws InterruptedException 
      {
         //判断
         while(number!=1) {
           this.wait();
         }
         //干活
         --number;
         System.out.println(Thread.currentThread().getName()+" 	 "+number);
         //通知
         this.notifyAll();
      }*/
    }
     
    /**
     * 
     * @Description:
     *现在两个线程,
     * 可以操作初始值为零的一个变量,
     * 实现一个线程对该变量加1,一个线程对该变量减1,
     * 交替,来10轮。 
     *
     *  * 笔记:Java里面如何进行工程级别的多线程编写
     * 1 多线程变成模板(套路)-----上
     *     1.1  线程    操作    资源类  
     *     1.2  高内聚  低耦合
     * 2 多线程变成模板(套路)-----下
     *     2.1  判断
     *     2.2  干活
     *     2.3  通知
     
     */
    public class NotifyWaitDemo
    {
      public static void main(String[] args)
      {
         ShareData sd = new ShareData();
         new Thread(() -> {
     
           for (int i = 1; i <= 10; i++) {
              try {
                sd.increment();
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
           }
         }, "A").start();
         
         new Thread(() -> {
     
           for (int i = 1; i <= 10; i++) {
              try {
                sd.decrement();
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
           }
         }, "B").start();
         new Thread(() -> {
     
           for (int i = 1; i <= 10; i++) {
              try {
                sd.increment();
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
           }
         }, "C").start();
         new Thread(() -> {
     
           for (int i = 1; i <= 10; i++) {
              try {
                sd.decrement();
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
           }
         }, "D").start();
         
      }
    }
     
     
     
     
     
    /*
     * * 
     * 2 多线程变成模板(套路)-----下
     *     2.1  判断
     *     2.2  干活
     *     2.3  通知
     * 3 防止虚假唤醒用while
     * 
     * 
     * */
     
     
    
  • 相关阅读:
    一个Web文件上传的C#源代码
    DataSets and Serialization 数据集和序列化 (英文版)
    如何在Unity中播放影片
    靠边伸缩菜单的做法(类似QQ,碰到就会伸出来)
    Lightmapper
    Unity官方教學專案 Character Customization (紙娃娃系統)
    unity3d用鼠标拖动物体的一段代码
    [unity3d程序] 颜色渐变效果
    C# typeof()实例详解
    XNA Billboard(公告板技术)
  • 原文地址:https://www.cnblogs.com/cb1186512739/p/12736023.html
Copyright © 2011-2022 走看看