• 多线程04-线程同步通信


    1.问题的引入

         存在一个面试题:

          编写代码实现子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,然后再回到主线程又循环100次,如此循环50次。

    2.问题分析

         首先,明确问题中存在两个线程: 一个子线程 一个main线程,线程循环一次要中循环体的内容需要保证为一个整体(即需要对改内容同步,如上次说的打印姓名的例子一样,

    打印张三的名字没有完成就不能打印李四的名字) 因此需要对操作进行同步 。

         其次,子线程循环一次后是主线程循环,如此往复50次,那么两者之间就需要通信 告诉对象自己执行结束需要对象来执行 

    3.编码实现

         

    package org.lkl.thread;
    /**
     * 线程同步通信
     * @author Liaokailin
     *
     */
    public class ThreadCommunication {
    
        
    
        
        
        public static void main(String[] args) {
            //子线程和主线程都是通过同一个对象b来调用其具体的方法 由于该方法加了synchronized关键字 那么两个能同步
            final Business b = new Business() ;
            /**
             * 这里为子线程操作
             */
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    for(int i = 1 ;i<=50 ;i++){
                        b.sub(i) ;
                    }
                }
            }).start() ;
            
            for(int i = 1 ;i<=50 ;i++){
                b.main(i) ;
            }
        }
    }
    
    
    /**
     * 子线程循环10次,接着主线程循环100次 
     * 对应的循环内容就是具体的业务操作 ,可以将其包装为一个类
     */
    
    
    class Business{
        
        private boolean flag = true ; //标记位
        /**
         * 子线程要实现的业务  需要同步
         * @param i
         */
        public synchronized void sub(int i){
            while(!flag){ //这里也可以使用if关键字  但是由于if可能会出现线程的假唤醒操作 通过while循环可以避免该问题
                try {
                    wait() ; //不为真 表示当前属于main线程执行  ,此方法进入等待状态
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for(int j =1 ;j<=10;j++){
                System.out.println("sub thread sequence of " + j +",loop of "+i);
            }
            flag = false ;
            notify() ;
        }
        
        /**
         * 主线程要实现的业务  需要同步
         * @param i
         */
        public synchronized void main(int i){
            
            while(flag){
                try {
                    wait() ; //为真 表示应为为子线程执行  此方法进入等待状态
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            for(int j =1 ;j<=100;j++){
                System.out.println("main thread sequence of " + j +",loop of "+i);
            }
            
            flag = true ; //修改标记位  让子线程来执行  但此时子线程可能在wait状态 需要进行唤醒操作 
            
            notify() ;
        }
        
        //备注: 线程的执行都是由cpu进行调度的 如果时间片到了子线程 但是子线程处于等待状态  那么cpu将调度其他线程来执行
    }

     4. 小结

        通过wait 和notify 来实现线程之间的通信

        要用到共同数据(包括同步锁) 的若干个方法或者共同算法应该归在同一个类上  !!!

  • 相关阅读:
    .NET : 单元测试到底给我们带来什么
    .NET : 如何将16进制颜色代码转换为十进制
    LINQ : 谈谈LINQ TO SQL中的直接加载和延迟加载
    .NET : 单元测试的几个Attribute介绍
    .NET : 在单元测试中使用外部文件作为数据源
    再来谈谈json
    .NET : 关于图片格式的问题
    VSTS : 比较性能基准
    .NET : 如何将大文件写入到数据库中
    LINQ : 如何在JOIN或者GROUP BY的时候使用复合键
  • 原文地址:https://www.cnblogs.com/liaokailin/p/3782837.html
Copyright © 2020-2023  润新知