• Java 多个线程之间共享数据


    线程执行的代码相同

       如果每个线程执行的代码相同,可以使用同一个Runnable对象,在这个Runnable对象中定义共享数据即可,例如,卖票系统就可以这么做。

    public class SellTicket {
        //卖票系统,多个窗口的处理逻辑是相同的
        public static void main(String[] args) {
            Ticket t = new Ticket();
            new Thread(t).start();
            new Thread(t).start();
        }}
    
    /**
     * 将属性和处理逻辑封装在同一个类中
     *
     * @author Wiener
     */
     class Ticket implements Runnable {
        // 资源初始值
        private int ticket = 10;
    
        public synchronized void run() {
            while (ticket > 0) {
                ticket--;
                System.out.println("当前票数为:" + ticket);
            }
        }}
    

    每个线程执行的代码不同

       如果每个线程执行的代码不同,这时候需要用不同的Runnable对象。例如,银行存取款系统中设计2个线程,一个线程对j增加1,另外一个线程对j减1。

       将共享数据抽象到一个类中,并将对这个数据的操作作为这个类的方法,这么设计可以轻而易举地做到同步,只要在方法上加synchronized关键字即可。

    package com.hoss.ext.authentication;
    
    /**
     * 两个线程执行的方法不一样
     *
     * @author Wiener
     * @date 2021/4/25
     */
    public class MultiThreadShareData {
        // 库存10
        private int j = 10;
    
        public static void main(String[] args) {
            MultiThreadShareData multiThreadShareData = new MultiThreadShareData();
            for (int i = 0; i < 2; i++) {
                //增加
                new Thread(multiThreadShareData.new ShareData1()).start();
                //减少
                new Thread(multiThreadShareData.new ShareData2()).start();
            }
        }
    
        //自增
        private synchronized void Inc() {
            j++;
            System.out.println(Thread.currentThread().getName() + " inc " + j);
        }
    
        //自减
        private synchronized void Dec() {
            j--;
            System.out.println(Thread.currentThread().getName() + " dec " + j);
        }
    
        class ShareData1 implements Runnable {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    Inc();
                }
            }
        }
    
        class ShareData2 implements Runnable {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    Dec();
                }
            }
        }
    }
    

       执行结果如下:

    Thread-1 dec 9
    Thread-1 dec 8
    Thread-1 dec 7
    Thread-1 dec 6
    Thread-1 dec 5
    Thread-3 dec 4
    Thread-3 dec 3
    Thread-3 dec 2
    Thread-3 dec 1
    Thread-3 dec 0
    Thread-2 inc 1
    Thread-2 inc 2
    Thread-2 inc 3
    Thread-2 inc 4
    Thread-2 inc 5
    Thread-0 inc 6
    Thread-0 inc 7
    Thread-0 inc 8
    Thread-0 inc 9
    Thread-0 inc 10

       关键还是思想:将共享数据和业务处理逻辑封装在一个类中,业务逻辑线程对象(即加1的线程和减1的线程操作)在执行时,直接调用该类中的处理逻辑。这样做,更符合面向对象,更易于维护。

       总结一下,对于多线程间共享变量的操作,需要实现互斥,使得对该共享变量的操作实现原子性。

    Reference


      读后有收获,小礼物走一走,请作者喝咖啡。

    赞赏支持

  • 相关阅读:
    再不努力提高效率,小姐姐都被人追走了:K8S一键部署了解一下?
    Spring Cloud和netflix 提供的Eureka等组件之间的版本关系
    启动kafka保错:命令过长语法不正确
    SpringBoot2.0 Config客户端自动刷新时没有/bus/refresh端点
    springcloud config配置采坑 Could not resolve placeholder 'from' in value "${from}报错,巨坑!
    Windows 下安装RabbitMQ服务器及基本配置
    linux 查看日志
    spring 事务原理
    IDEA 配置
    python中给定两个列表,怎么找出他们相同的元素和不同的元素?
  • 原文地址:https://www.cnblogs.com/east7/p/14701935.html
Copyright © 2020-2023  润新知