同步主题 - 家庭作业

时间:2012-11-22 20:25:45

标签: java multithreading synchronization

我需要运行一个名为ArrayHolder的java程序,它将运行两个ThreadsArrayHolder将有一个ArrayThreadSeven将使用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;
    }
}

2 个答案:

答案 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, ...的线程;您必须更改ThreadOneThreadSeven的实施。您现在可以做出的更好的解决方案是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内同步访问将非常棘手,因为它需要确保两个线程都以正确的顺序写入每个索引。

但我认为你的总体想法还可以。你只需要确保它是安全的