如何在 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/