多线程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 来实现线程之间的通信

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

原文地址:https://www.cnblogs.com/liaokailin/p/3782837.html