-5

我有一个大小为 n 的数组,其中填充了数字 1..n。

我需要使用 m 个线程对这个数组求和,每次取两个元素,将它们相加并将总和插入回数组中。

这是我试图做的。

先同步部分

public class MultiThreadedSum {

    private ArrayBuffer ArrayBufferInst;
    private int Sum;
    private boolean Flag, StopFlag;

    public MultiThreadedSum(ArrayBuffer ArrayBufferInst) {
        this.ArrayBufferInst = ArrayBufferInst;
        Sum = 0;
        Flag = false;
        StopFlag = false;
    }

    public synchronized void Sum2Elements() {
        while(Flag){
            try {wait();}
            catch (InterruptedException e){}
        }
        Flag = true;
        if (StopFlag) {
            notifyAll();
            return;
        }
        System.out.println("Removing and adding 2 elements.");
        Sum = ArrayBufferInst.Sum2Elements();
        notifyAll();
    }

    public synchronized void InsertElement() {

        while(!Flag){
            try {wait();}
            catch (InterruptedException e){}
        }
        Flag = false;
        if (StopFlag) {
            notifyAll();
            return;
        }
        System.out.println("Inserting the sum.");
        ArrayBufferInst.InsertElement(Sum);
        if (ArrayBufferInst.RetunrSize() == 1) {
            StopFlag = true;
        }
        System.out.println(ArrayBufferInst);
        notifyAll();
    }

    public boolean ReturnStopFlag(){
        return StopFlag;
    }

    @Override
    public String toString(){
        return ArrayBufferInst.toString();
    }
}

我已将 m 个线程分成 2 组,其中一半将进行汇总,另一半将使用等待和通知进行添加。

public class Sum2ElementsThread implements Runnable{
    private MultiThreadedSum MultiThreadedSumInst;    
    public Sum2ElementsThread( MultiThreadedSum MultiThreadedSumInst){
        this.MultiThreadedSumInst = MultiThreadedSumInst;
    }

    @Override
    public void run() {
        while(!MultiThreadedSumInst.ReturnStopFlag())
            MultiThreadedSumInst.Sum2Elements();
    }
}

public class InsertThread implements Runnable{
    private MultiThreadedSum MultiThreadedSumInst;    
    public InsertThread( MultiThreadedSum MultiThreadedSumInst) {
        this.MultiThreadedSumInst = MultiThreadedSumInst;
    }

    @Override
    public void run() {
        while(!MultiThreadedSumInst.ReturnStopFlag())  {
            MultiThreadedSumInst.InsertElement();
        }
    }
}

以下是主要内容的一部分:

ArrayBufferInst = new ArrayBuffer(n);

System.out.println("The Array");
System.out.println(ArrayBufferInst);

MultiThreadedSumInst = new MultiThreadedSum(ArrayBufferInst);

ExecutorService Threads = Executors.newCachedThreadPool();

for (i = 0; i < m/2; i++)
    Threads.execute( new Sum2ElementsThread(MultiThreadedSumInst) );
for (; i < m; i++)
    Threads.execute( new InsertThread(MultiThreadedSumInst) );
Threads.shutdown();
while(!MultiThreadedSumInst.ReturnStopFlag()){}
System.out.println("The sum of the array is " + MultiThreadedSumInst);

和缓冲区

public class ArrayBuffer {
    private ArrayList<Integer> ArrayBufferInst;
    public ArrayBuffer(int SizeOfBuffer){
        int i;
        ArrayBufferInst = new ArrayList<>(SizeOfBuffer);
        for (i = 0; i < SizeOfBuffer; i++){
            ArrayBufferInst.add(i, i+1);
        }
    }

    public int Sum2Elements(){
        if (ArrayBufferInst.size() < 2){
            return -1;
        }
        return ArrayBufferInst.remove(0) + ArrayBufferInst.remove(0);
    }

    public void InsertElement(int Elem) {
        ArrayBufferInst.add(Elem);
    }
    public int RetunrSize(){
        return ArrayBufferInst.size();
    }
    @Override
    public String toString() {
        return ArrayBufferInst.toString();
    }
}

我的问题是关于 main 的结束,有时程序停止,有时没有,我知道所有线程都退出 run 方法,因为我检查了它。

有时我会看到The sum of the array is消息,有时我不会。

4

2 回答 2

1

你的问题出在这里:

public synchronized void Sum2Elements() {
    while(Flag){
        try {wait();}
        catch (InterruptedException e){}
    }
    Flag = true;
    // rest of method omitted here
}

当这部分程序第一次执行时Flag为假,循环被忽略。Flag此方法的所有后续执行都将导致死锁,因为这是您设置为 false的唯一位置。

甚至中断都不会起作用,因为您break的循环中没有任何内容,并且在中断之后您将继续进行下一个循环并且wait()永远。

哦,请阅读- Java 不是 c#

于 2013-05-22T07:16:16.797 回答
0

对于您的任务来说,这确实是一个很长的代码。

也许我可以提出不同的解决方案。您可以将数组拆分为 m 个部分(m - 是线程数) - 每个线程都会对它自己的部分求和。当每个线程中的求和结束时 - 只需对所有部分结果求和。

或者,也许我没有正确完成您的任务。请指定更多细节(完整任务)。

于 2013-05-22T06:49:54.720 回答