如何在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
依此类推,直到它到达数组中的最后一个元素。
答案 0 :(得分:2)
您的线程已同步Input.index
的访问权限,因此Input
类正常。你真正的问题在于MyThread.run
。这两行:
System.out.println(t.getName());
ip.print(index);
对System.out.println
进行2次单独调用。在多线程上下文中,它们必然在线程之间交错,因此输出将超出(全局)顺序。
如果你想保证2个电话是不可分割的,你需要对这2个电话进行排序" atomic" (像同步块一样)。您必须在线程之间共享一个锁,以保护对此代码块的访问,并使它们的执行相互排斥。他们可以共享锁定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
数组中的确切顺序。
BTW,在构造函数中启动Thread
是危险的,应该避免。我对您的原始代码进行了细微更改。
答案 1 :(得分:0)
您可以使用低级等待通知方法使用以下方法。
package com.thread;
/*Print 1 to 15 together by 2 threads*/
public class Print1To15 {
static int[] input = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread(input);
MyThread t2 = new MyThread(input);
Thread thread1 = new Thread(t1, "Thread 1");
Thread thread2 = new Thread(t2, "Thread 2");
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}
class MyThread implements Runnable {
int[] array;
static int i = 0;
final static Object obj = new Object();
MyThread(int[] array) {
this.array = array;
}
@Override
public void run() {
synchronized (obj) {
while (i <= 14) {
if (array[i] % 2 != 0 && Thread.currentThread().getName().equals("Thread 1")) {
System.out.println(Thread.currentThread().getName() + " printing " + array[i]);
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (array[i] % 2 == 0 && Thread.currentThread().getName().equals("Thread 2")) {
System.out.println(Thread.currentThread().getName() + " printing " + array[i]);
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i++;
obj.notifyAll();
}
}
}
}