zoukankan      html  css  js  c++  java
  • 多线程的通讯之共享内存篇(synchroniezd方式)

      多线程的通讯方式有如下几种方式,今天我们首先简绍线程通讯之共享内存

      1.共享内存

      首先,我们通过一个经典的多线程案例开启我们的多线程的之旅。

      有这么个要求:子线程执行10次,主线程执行100次,两者交替50次。

      

    package com.sort.test;
    
    public class SynThreadTest {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            //子线程执行10次,主线程执行100次,两者交替50次。
            //业务对象必须是同一个对象(这里指tran这个对象),不能是两个对象,两个对象的同步方法不会互斥,也就达不到同步的效果了
            final Transacion tran = new Transacion();
            //启动子线程
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    for(int i = 0; i < 10; i++){
                        tran.sub(i);
                    }
                }
            }).start();
            //主线程中执行50次
            for(int i = 0; i < 10; i++){
                tran.main(i);
            }
        }
        
        
    }
    /**
     * 业务类
     * @author zhangli
     *
     */
    class Transacion{
        //共享内存中的共享变量
        private boolean isMainTurn = false; 
        public synchronized void main(int j){
            //首先判断是否是主线程轮次,如果是ture,则主线程执行100次,否则主线程等待
            if(!isMainTurn){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            //完成主线程任务
            for (int i = 0 ; i < 100 ;i++){
                
                System.out.println("主线程执行第"+j+"次"+"序号为"+i);
            }
            //执行100次后,主线程本轮执行完毕,改变共享变量通知子线程执行
            isMainTurn = false;
            //释放this锁,并且唤醒等待此对象的上的子线程,让它进入就绪状态
            this.notify();
        }
        public synchronized void sub(int j){
            //首先判断是否是子线程轮次,如果是false,则子线程执行10次,否则子线程等待
            if(isMainTurn){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            //完成子线程任务
            for (int i = 0 ; i < 10 ;i++){
                System.out.println("子线程执行第"+j+"次"+"序号为"+i);
            }
            //执行10次后,子线程本轮执行完毕,改变共享变量通知子线程执行
            isMainTurn = true;
            //释放this锁,并且唤醒等待此对象的上的主线程,让它进入就绪状态
            this.notify();
        }
    }

      执行结果如下:

    主线程执行第0次序号为86
    主线程执行第0次序号为87
    主线程执行第0次序号为88
    主线程执行第0次序号为89
    主线程执行第0次序号为90
    主线程执行第0次序号为91
    主线程执行第0次序号为92
    主线程执行第0次序号为93
    主线程执行第0次序号为94
    主线程执行第0次序号为95
    主线程执行第0次序号为96
    主线程执行第0次序号为97
    主线程执行第0次序号为98
    主线程执行第0次序号为99
    123123
    子线程执行第1次序号为0
    子线程执行第1次序号为1
    子线程执行第1次序号为2
    子线程执行第1次序号为3
    子线程执行第1次序号为4
    子线程执行第1次序号为5
    子线程执行第1次序号为6
    子线程执行第1次序号为7
    子线程执行第1次序号为8
    子线程执行第1次序号为9
    主线程执行第1次序号为0
    主线程执行第1次序号为1
    主线程执行第1次序号为2
    主线程执行第1次序号为3
    主线程执行第1次序号为4
    主线程执行第1次序号为5
    主线程执行第1次序号为6
    主线程执行第1次序号为7
    主线程执行第1次序号为8
    主线程执行第1次序号为9
    主线程执行第1次序号为10
    主线程执行第1次序号为11

      在此案例中,我们是利用同一个对象tran的isMainTurn属性完成多线程通讯的,通过改变isMainTurn的属性值以判断该是哪个线程的轮次,这样完成了线程的同步和通讯。

      总结:

      1.共享变量必须是同一个对象(这里指tran这个对象),不能是两个对象,两个对象的同步方法不会互斥,也就达不到同步的效果了

      2.在利用共享变量处理多线程问题时,我们最好根据实际定义一个业务类,也就是把我们要同步的多个任务最好封装到一个业务类中,这样我们就可以通过一个业务类对象完成多个任务的同步了。

      3.锁都是加在对象上(tran)的,而不是加在方法上的

      4.wait方法会立刻阻塞本次线程执行,而且释放线程上的对象锁;而notify也会释放线程上的对象锁,但不会阻塞线程的执行。

      

  • 相关阅读:
    课程安排及脉络
    面向对象 魔法方法 单例(五)
    练习项目:选课系统
    面向对象 多态 类方法 反射 (四)
    面向对象(三) 组合 封装
    面向对象编程(二)
    面向对象编程(一)
    python入门总复习
    模块(四)
    模块(三)
  • 原文地址:https://www.cnblogs.com/fengyan20150508/p/7828477.html
Copyright © 2011-2022 走看看