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 @ 2021-04-25 20:33  楼兰胡杨  阅读(1271)  评论(0编辑  收藏  举报