Java多线程中共享数据的几种方法总结

Java Q&A Hub 使用 GPT-4o-mini 回答

问题:

Java面试题之多线程 如何在两个线程间共享数据?

回答:

在Java中,多个线程之间共享数据可以通过多种方式实现。以下是一些常见的方法:

1. 使用共享对象

可以通过创建一个共享对象,多个线程可以访问和修改这个对象的属性。

class SharedData {
    private int data;

    public synchronized int getData() {
        return data;
    }

    public synchronized void setData(int data) {
        this.data = data;
    }
}

class ThreadA extends Thread {
    private SharedData sharedData;

    public ThreadA(SharedData sharedData) {
        this.sharedData = sharedData;
    }

    public void run() {
        sharedData.setData(10);
    }
}

class ThreadB extends Thread {
    private SharedData sharedData;

    public ThreadB(SharedData sharedData) {
        this.sharedData = sharedData;
    }

    public void run() {
        System.out.println(sharedData.getData());
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        SharedData sharedData = new SharedData();
        ThreadA threadA = new ThreadA(sharedData);
        ThreadB threadB = new ThreadB(sharedData);
        
        threadA.start();
        threadB.start();
    }
}

2. 使用volatile关键字

如果一个变量被多个线程共享,并且只在一个线程中被写入,其他线程只读取这个变量,可以使用volatile关键字来确保可见性。

class SharedData {
    private volatile int data;

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }
}

3. 使用wait()notify()

可以使用对象的监视器来实现线程间的通信。一个线程可以调用wait()方法等待另一个线程的通知,而另一个线程可以调用notify()notifyAll()方法来唤醒等待的线程。

class SharedData {
    private int data;
    private boolean available = false;

    public synchronized int getData() throws InterruptedException {
        while (!available) {
            wait();
        }
        available = false;
        notify();
        return data;
    }

    public synchronized void setData(int data) throws InterruptedException {
        while (available) {
            wait();
        }
        this.data = data;
        available = true;
        notify();
    }
}

4. 使用CountDownLatchCyclicBarrier等并发工具类

Java的java.util.concurrent包提供了许多并发工具类,可以帮助管理线程间的共享数据和同步。

import java.util.concurrent.CountDownLatch;

class SharedData {
    private int data;

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        SharedData sharedData = new SharedData();
        CountDownLatch latch = new CountDownLatch(1);

        Thread threadA = new Thread(() -> {
            sharedData.setData(10);
            latch.countDown(); // 释放锁
        });

        Thread threadB = new Thread(() -> {
            try {
                latch.await(); // 等待线程A完成
                System.out.println(sharedData.getData());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        threadA.start();
        threadB.start();
    }
}

总结

在Java中,线程间共享数据的方式有很多,选择合适的方法取决于具体的应用场景和需求。使用共享对象、volatile关键字、wait()notify()方法,以及并发工具类都是常见的选择。确保在多线程环境中正确处理共享数据的可见性和同步性是非常重要的。