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

posted @   楼兰胡杨  阅读(1280)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示