我需要运行一个名为ArrayHolder
的java程序,它将运行两个Threads
。 ArrayHolder
将有一个Array
。 ThreadSeven
将使用7覆盖Array
的每个元素,并使用{覆盖ThreadOne
。
执行后的结果应该是7,1,7,1,7,1,7,1等。我已经解决了这个问题,虽然我不喜欢我的解决方案,希望你能提出更好的方法。
p.s:两个线程都必须写入所有索引。
public class ArrayHolder {
private int[] array = {1, 2, 3, 4, 5, 6, 4, 8, 9, 10};
public void writeInt(int pos, int num) {
array[pos] = num;
}
public static void main(String[] args) {
ArrayHolder holder = new ArrayHolder();
ThreadSeven seven = new ThreadSeven(holder, null);
Runnable one = new ThreadOne(holder, seven);
Thread thread1 = new Thread(seven);
Thread thread2 = new Thread(one);
seven.setThread(one);
thread1.start();
thread2.start();
holder.printArray();
}
private void printArray() {
for (int i = 0; i < 10; i++) {
System.out.println(array[i]);
}
}
public class ThreadSeven implements Runnable {
private ArrayHolder array;
private Runnable t;
private int flag=0;
@Override
public void run() {
for(int i=0;i<10;i++){
array.writeInt(i, 7);
flag=(flag+1)%2;
if (flag==0){
synchronized(t){
t.notify();
}
}else{
synchronized(this){
try {
this.wait();
} catch (InterruptedException ex) {
Logger.getLogger(ThreadSeven.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
public ThreadSeven (ArrayHolder ar,Runnable t){
array=ar;
this.t=t;
}
public void setThread(Runnable t){
this.t=t;
}
}
public class ThreadOne implements Runnable {
private ArrayHolder array;
private Runnable t;
private int flag = 0;
@Override
public void run() {
for (int i = 0; i < 10; i++) {
array.writeInt(i, 1);
flag = (flag + 1) % 2;
if (flag == 1) {
synchronized (t) {
t.notify();
}
} else {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException ex) {
Logger.getLogger(ThreadSeven.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
public ThreadOne(ArrayHolder ar, Runnable t) {
array = ar;
this.t = t;
}
public void setThread(Runnable t) {
this.t = t;
}
}
答案 0 :(得分:2)
ThreadSeven和ThreadOne不需要是单独的类;看起来您只需复制/粘贴代码,然后将writeInt中的7
更改为1
。相反,您可以对此值进行参数化并将其传递给构造函数。然后你得到类似的东西:
public class ThreadWriter implements Runnable {
private final int numberToWrite;
// ...
public ThreadOne(ArrayHolder ar, Runnable t, int numberToWrite) {
array = ar;
this.t = t;
this.numberToWrite = numberToWrite;
}
// ...
}
另一点是你的两个线程必须彼此了解;这不能很好地扩展。假装你的下一个任务,你的老师说你必须处理三个写1, 4, 7, 1, 4, 7, ...
的线程;您必须更改ThreadOne
和ThreadSeven
的实施。您现在可以做出的更好的解决方案是ThreadWriter
本身就是笨蛋,并在ArrayHolder
类(或中间ThreadWriterManager
类)中更多地管理他们的交互。
答案 1 :(得分:0)
您的解决方案存在一些问题,并且我认为它不会打印出正确的结果。
a)在打印生成的数组
之前,不要等待线程完成在thread1.join()
之前添加thread2.join()
和holder.printArray()
,以防它不存在。
b)两个线程都开始通过array.writeInt(0, /* 1 or 7 */);
立即写入。之后,他们开始互相等待。第一个指数是否正确取决于运气。
c)在没有循环检查条件的this.wait();
之后继续检查是不安全的,因为中断可能是由其他线程引起的。我想这可以在这里做,因为它只是一个练习。
d)我看到一个潜在的死锁:让我们假设两个线程仍在编写第一个索引。所以两者都不在同步块中。
必须通知另一个的线程这样做,写下一个索引并进入它自己的等待块。
但是第二个线程当时没有等待,所以第一个线程的notify
什么也没做。第二个线程也进入等待块。
现在两个线程都互相等待,不再发生任何事情。
我没有一个很好的简单解决方案,因为这个问题非常复杂。
1线程需要开始在索引0处写入然后等到7线程写入索引0和1,现在1线程写入索引1和2并等待等等。这是我认为可以确保两个线程都写入每个索引并且结果是7-1-7-1的唯一方法 - 在ArrayHolder
内同步访问将非常棘手,因为它需要确保两个线程都以正确的顺序写入每个索引。
但我认为你的总体想法还可以。你只需要确保它是安全的