zoukankan      html  css  js  c++  java
  • 多线程范围内的数据共享

    多线程范围内的共享解决方法参考有4中:

    1.如果线程执行的代码相同,多个线程共享同一个runnable对象时,将共享数据放在runnable对象

    2.如果多个线程执行的代码不同,将共享数据封装到一个对象中,将这个对象逐一传递给各个runnable对象

    3.如果多个线程执行的代码不同,将共享数据作为外部类的final成员变量,将不同的runnable对象作为内部类主动取数据

    4.将数据声明为static的方式()

    见如下示例:

    1.如果线程执行的代码相同,多个线程共享同一个runnable对象时,将共享数据放在runnable对象

    public class MuiltThreadShare {
        /**
         * 多个线程共享数据方法:
         * 1.如果线程执行的代码相同,多个线程共享同一个runnable对象时,将共享数据放在runnable对象
         * 2.如果多个线程执行的代码不同,将共享数据封装到一个对象中,将这个对象逐一传递给各个runnable对象
         * 3.如果多个线程执行的代码不同,将共享数据作为外部类的final成员变量,将不同的runnable对象作为内部类主动取数据
         */
        
        public static void main(String[] args) {
            //1.方式一
            Task1 task1 = new Task1();
            new Thread(task1).start();
            new Thread(task1).start();
            new Thread(task1).start();
            
            
            
        }
        
    
    }
    
    class Task1 implements Runnable{
        /**
         * 1.如果线程执行的代码相同,多个线程共享同一个runnable对象时,将共享数据放在runnable对象
         */
        
        private int i = 100;
    
        @Override
        public void run() {
            increase();
            decrease();
        }
        
        private synchronized void increase(){
            try {
                Thread.sleep(200);//为了更容易看到线程执行现象
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            i++;
            System.out.println(Thread.currentThread().getName() +",num:"+i);
        }
        private synchronized void decrease(){
            i--;
            System.out.println(Thread.currentThread().getName() +",num:"+i);
        }

    运行结果:最终还是100,不同的线程使用共享数据

    运行结果
    //    Thread-0,num:101
    //    Thread-2,num:102
    //    Thread-1,num:103
    //    Thread-2,num:102
    //    Thread-0,num:101
    //    Thread-1,num:100

    2.如果多个线程执行的代码不同,将共享数据封装到一个对象中,将这个对象逐一传递给各个runnable对象

    public class MuiltThreadDataShare2 {
        public static void main(String[] args) {
            // 2.如果多个线程执行的代码不同,将共享数据封装到一个对象中,将这个对象逐一传递给各个runnable对象
            /**
             * 模拟银行转账功能,可以指定存取款金额,账号初始额度100
             */
            ShareData data = new ShareData(0);
    
            // 存50元
            new Thread(new TaskIncrease(data, 50)).start();
            // 取30元
            new Thread(new Taskdecrease(data, 30)).start();
            // 存20
            new Thread(new TaskIncrease(data, 20)).start();
    
        }
    
    }
    
    class Taskdecrease implements Runnable {
        public Taskdecrease(ShareData shareData, int num) {
            this.shareData = shareData;
            this.num = num;
        }
    
        private int num;
    
        private ShareData shareData;
    
        @Override
        public void run() {
            shareData.decrease(num);
        }
    
    }
    
    class TaskIncrease implements Runnable {
        public TaskIncrease(ShareData shareData, int num) {
            this.shareData = shareData;
            this.num = num;
        }
    
        private ShareData shareData;
        private int num;
    
        @Override
        public void run() {
            shareData.increase(num);
        }
    
    }
    
    class ShareData {
        public ShareData(int num) {
            i = num;
            System.out.println("账户进行初始化,金额为:" + num);
        }
    
        private int i;
    
        public synchronized void increase(int i) {
            try {
                Thread.sleep(200);// 为了更容易看到线程执行现象
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.i = this.i + i;
            System.out.println(Thread.currentThread().getName() + "账户存入" + i + "元,目前账户余额为:" + this.i);
        }
    
        public synchronized void decrease(int i) {
            this.i = this.i - i;
            System.out.println(Thread.currentThread().getName() + "账户取出" + i + "元,目前账户余额为:" + this.i);
        }
    }

    运行结果:

    账户进行初始化,金额为:0
    Thread-0账户存入50元,目前账户余额为:50
    Thread-2账户存入20元,目前账户余额为:70
    Thread-1账户取出30元,目前账户余额为:40

    3.如果多个线程执行的代码不同,将共享数据作为外部类的final成员变量,将不同的runnable对象作为内部类主动取数据

    public class MuiltThreadDataShare3 {
    
    
        public static void main(String[] args) {
            final Data data = new Data();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    data.decrease(10);
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    data.increase(30);
                }
            }).start();
    
        }
    
    }
    
    class Data {
        private int money = 100;
    
        public int getMoney() {
            return money;
        }
    
        public void setMoney(int money) {
            this.money = money;
        }
    
        public synchronized void increase(int i) {
            try {
                Thread.sleep(200);// 为了更容易看到线程执行现象
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.money = this.money + i;
            System.out.println(Thread.currentThread().getName() + "账户存入" + i + "元,目前账户余额为:" + this.money);
        }
    
        public synchronized void decrease(int i) {
            this.money = this.money - i;
            System.out.println(Thread.currentThread().getName() + "账户取出" + i + "元,目前账户余额为:" + this.money);
        }
    
    }

    4.将数据声明为static的方式

    public class MuiltThreadDataShare4 {
        private static int num = 100;
    
        public static void main(String[] args) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    increase(100);
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    decrease(30);
                }
            }).start();
        }
    
        public static synchronized void increase(int i) {
            try {
                Thread.sleep(200);// 为了更容易看到线程执行现象
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            num = num + i;
            System.out.println(Thread.currentThread().getName() + "账户存入" + i + "元,目前账户余额为:" + num);
        }
    
        public static synchronized void decrease(int i) {
            num = num - i;
            System.out.println(Thread.currentThread().getName() + "账户取出" + i + "元,目前账户余额为:" + num);
        }
    
    }

  • 相关阅读:
    通过set和waitOne来控制子线程的运行和停止
    一种控制线程运行和停止的方法
    C# 运用params修饰符来实现变长参数传递
    ref和out的区别
    C# 抽象类和接口的区别
    更有效率的使用Visual Studio(一)
    更有效率的使用Visual Studio(二)
    RS232串口用事件接受数据(一问一答)
    socket的异步回调函数,采用一问一答
    js去重方法
  • 原文地址:https://www.cnblogs.com/zhangshiwen/p/5042331.html
Copyright © 2011-2022 走看看