zoukankan      html  css  js  c++  java
  • Java线程——线程之间的数据共享

     
    在 Java 传统线程机制中的共享数据方式,大致可以简单分两种情况:
    ➢ 多个线程行为一致,共同操作一个数据源。也就是每个线程执行的代码相同,可以使用同一个 Runnable 对象,这个 Runnable 对象中有那个共享数据,例如,卖票系统就可以这么做。
    ➢ 多个线程行为不一致,共同操作一个数据源。也就是每个线程执行的代码不同,这时候需要用不同的Runnable 对象。例如,银行存取款。 
     
    实例1:多个线程行为一致共同操作一个数据
     
      如果每个线程执行的代码相同,可以使用同一个 Runnable 对象,这个 Runnable 对象中有那个共享数据,例如,买票系统就可以这么做。
    package com.itheima.gan;
    //买票系统
    //共享数据类
    class  ShareDate{
        private int num=10;   //10张票
        
        public synchronized void inc() {
            num++;
            System.out.println(Thread.currentThread().getName()+
                    ": invoke inc method num="+num);
            try {
                //线程休眠1s
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 多线程类
     * @author 12428
     *
     */
    public class RunnableCusToInc implements Runnable{
    
        private ShareDate shareDate;
        //构造方法,将数据传递进去
        public RunnableCusToInc(ShareDate shareDate) {
            this.shareDate=shareDate;
        }
        //线程应该做的事
        @Override
        public void run() {
            for(int i=0;i<5;i++) {
                shareDate.inc();
            }
            
        }
    
        public static void main(String[] args) {
            ShareDate shareDate=new ShareDate();
            
            for(int i=0;i<4;i++) {
                new Thread(new RunnableCusToInc(shareDate),"线程"+i).start();
            }
        }
    }

    实例2:多个线程行为不一致共同操作一个数据 

    如果每个线程执行的代码不同,这时候需要用不同的 Runnable 对象,有如下两种方式来实现这些 Runnable 对象之间的数据共享

     (1)将共享的数据放到一个对象中,在把这个对象逐一传递给各个Runnable对象,每个线程对该数据的操作也放在这个对象的不同方法中,这样说实现容易针对对该数据进行的各个操作的互斥和通信。

    package com.itheima.gan;
    
    class RunnableCusToDec implements Runnable {
        private ShareDate1 shareDate;
    
        public RunnableCusToDec(ShareDate1 shareDate) {
            this.shareDate = shareDate;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                shareDate.dec();
            }
        }
    }
    
    
    public class RunnableCusToInc2 implements Runnable {
    
        private ShareDate1 shareDate;
    
        public RunnableCusToInc2(ShareDate1 shareDate) {
            this.shareDate = shareDate;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                shareDate.inc();
            }
        }
    
        public static void main(String[] args) {
            ShareDate1 shareDate1=new ShareDate1();
            for(int i=0;i<4;i++) {
                if(i%2==0) {
                    new Thread(new RunnableCusToInc2(shareDate1),"Thread"+i).start();
                }else {
                    new Thread(new RunnableCusToDec(shareDate1),"Thread"+i).start();
                }
            }
        }
    }
    
    /*
     * 共享数据类
     */
    class ShareDate1 {
        private int num = 10;
    
        public synchronized void inc() {
            num++;
            System.out.println(Thread.currentThread().getName() + ": invoke inc method num=" + num);
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public synchronized void dec() {
            num--;
            System.err.println(Thread.currentThread().getName() + ": invoke dec method num =" + num);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

      运行结果如图:

           

    (2)将这些 Runnable 对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable 对象调用外部类的这些方法。

    package com.itheima.gan;
    
    public class RunnableTest {
        public static void main(String[] args) {
            //公共数据
            final ShareDate2 shareDate=new ShareDate2();
            for(int i=0;i<4;i++) {
                if(i%2==0) {
                    new Thread(new Runnable() {
                        
                        @Override
                        public void run() {
                            for(int i=0;i<5;i++) {
                                shareDate.inc();
                            }
                            
                        }
                    },"Thread "+i).start();
                }else {
                    new Thread(new Runnable() {
                        
                        @Override
                        public void run() {
                            for(int i=0;i<5;i++) {
                                shareDate.dec();
                            }
                            
                        }
                    }).start();
                }
            }
        }
    }
    
    //公共数据类
    class ShareDate2{
        
        private int num=10;
        
        public  synchronized void inc() {
            num++;
            System.err.println(Thread.currentThread().getName()+" : invoke inc method  num = "+num);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        public synchronized void dec() {
            num--;
            System.out.println(Thread.currentThread().getName()+" : invoke dec method num = "+num);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }

      运行结果如图:

        

  • 相关阅读:
    Vue 多层组件传值(最外层组件>中间组件>最内部组件)
    Vue 父子组件传值 (Vue-cli4)
    CSS HTML 基本知识 盒子模型 Flex等
    Vue---基本知识
    springboot ---邮件和定时任务 和异步
    js中.bind()和.call()用法讲解
    为页内的tab添加的iframe添加加载动画过渡效果
    JMETER学习宝典
    新篇章,新起点
    计划拟定(现阶段)
  • 原文地址:https://www.cnblogs.com/zhilili/p/11981241.html
Copyright © 2011-2022 走看看