java - 我如何在 Java 中的多个线程之间共享资源?

标签 java multithreading

如何在 Java 中的多个线程之间共享一个类的数组?

假设我有一个名为 Input 的类,其数组如下所示:

public class Input {
    int index;
    int[] input = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

    public Input(){
        index = 0;
    }

    public void print(int index){
        System.out.println(input[index]);
    }

    synchronized public int getIndex(){
        if(index == 15)
            return -1;
        return index++;
    }

}

现在,我想要 2 个线程共享 Input 类的数组,并打印数组的元素(即两个线程一起打印总共应打印 15 次(数组中的元素数)。

这是我的线程类:

public class MyThread implements Runnable{

    Thread t;
    int index;
    Input ip;

    public MyThread(Input ip, String name){
        t = new Thread(this, name);
        this.ip = ip;
        index = 0;
        t.start();
    }

    @Override
    public void run() {     
        while((index=ip.getIndex())!=-1){
            System.out.println(t.getName());
            ip.print(index);
        }

    }   

}

最后,设置线程的代码:

public class Caller {

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        Input ip = new Input();
        MyThread t1 = new MyThread(ip, "Thread1");
        MyThread t2 = new MyThread(ip, "Thread2");
        t1.t.join();
        t2.t.join();

    }

}

输出应该是这样的:

线程1

1

线程2

2

线程2

3

线程1

4

线程2

5

依此类推,直到到达数组中的最后一个元素。

最佳答案

您的线程已同步访问 Input.index,因此 Input 类没问题。您真正的问题在于 MyThread.run。这两行:

    System.out.println(t.getName());
    ip.print(index);

System.out.println 进行 2 次单独调用。在多线程上下文中,它们必然会在线程之间交错,因此输出将是乱序的(全局)。

如果你想保证这 2 个调用是不可分割的,你需要使这 2 个调用有点“原子”(就像一个同步块(synchronized block))。您必须在线程之间共享锁以保护对此代码块的访问并使它们的执行互斥。它们可以共享锁 Object 上的内部锁,或使用 java.util.concurrent.locks.ReentrantLock 共享显式锁。

我给出了一个内在锁的示例代码:

public class MyThread implements Runnable{

    Input ip;
    Object lock;

    public MyThread(Input ip, Object lock){
        this.ip = ip;
        this.lock = lock;
    }

    @Override
    public void run() {
        int index = -1;     
        while((index=ip.getIndex())!=-1){
            synchronized(lock) {
                System.out.println(Thread.currentThread().getName());
                ip.print(index);
            }
        }
    }   
}


public class Caller {

    public static void main(String[] args) throws InterruptedException {
        Input ip = new Input();
        Object lock = new Object();
        Thread t1 = new Thread(new MyThread(ip, lock), "Thread1");
        Thread t2 = new Thread(new MyThread(ip, lock), "Thread2");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

请注意:这只会确保“ThreadX n”一起打印。它不保证输出遵循 Input 数组中的确切顺序。

顺便说一句,在构造函数中启动一个Thread 是危险的,应该避免。我对您的原始代码做了一些小改动。

关于java - 我如何在 Java 中的多个线程之间共享资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24625869/

相关文章:

java - 当客户端 VM 突然终止时,有状态 EJB 不会被钝化

java - 如何将模拟对象注入(inject)到构造函数中?

java - SQLite 异常 : no such column in Android

c# - 确保ThreadPool中的任务执行顺序

c# - 锁定公共(public)对象,并跨模块共享

java - 使用 Java 在 Android 中将接收 Intent 设置回默认值

java - Spring 数据休息 : RepositoryRestController deserialization from URI not working

java - Java 中的线程

android - 它是否允许在 Android SQLite 中一次创建多个事务

java - 如何以线程安全且高效的方式使用 XPath?