Java并行同步2个线程

时间:2015-12-16 07:36:50

标签: java multithreading synchronized

-----------------已解决,谢谢您的建议! ------------

我有以下代码,其中有一组数字。我想创建2个并行执行的线程。第一个打印数字值和第二个线程的线程相乘。 这是我的代码

class Synchronize {

    private boolean writeable = true;

    public synchronized void numbers() {
        {
            while (!writeable) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
            writeable = false;
            notify();
        }
    }

    public synchronized void multiply() {
        while (writeable) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        writeable = true;
        notify();
    }
}

class Numbers
        extends Thread {

    private Synchronize s;
    int   numbers = 0;
    int[] array;

    Numbers(String name, Synchronize s, int[] array) {
        super(name);
        this.s = s;
        this.array = array;
    }

    public void run() {
        try {
            for (int i = 0; i <= array.length - 1; i++) {
                System.out.print("\nIn " + getName() + " number is " + array[i] + "\t");
                Thread.sleep(1000);
                s.numbers();
            }
        } catch (Exception e) {
        }
    }
}


class Multiply
        extends Thread {

    private Synchronize s;
    int   multiply = 1;
    int[] array;

    Multiply(String name, Synchronize s, int array[]) {
        super(name);
        this.s = s;
        this.array = array;
    }

    public void run() {
        try {
            for (int i = 0; i <= array.length - 1; i++) {
                multiply = multiply * array[i];
                System.out.print("\nIn " + getName() + " multiply is " + multiply + "\t");
                Thread.sleep(1000);
                s.multiply();
            }
        } catch (Exception e) {
        }
    }
}


public class NewThread {

    public static void main(String[] args) {

        int array[] = {
                1,
                4,
                5,
                2,
                7,
                8,
                9
        };

        Synchronize s = new Synchronize();
        new Numbers("Thread #1 ", s, array).start();
        new Multiply("Thread #2 ", s, array).start();
    }
}

代码输出如下:

In Thread #1  number is 1   
In Thread #2  multiply is 1     
In Thread #1  number is 4   
In Thread #2  multiply is 4     
In Thread #2  multiply is 20    
In Thread #1  number is 5   
In Thread #1  number is 2   
In Thread #2  multiply is 40    
In Thread #1  number is 7
In Thread #1  number is 8   
In Thread #2  multiply is 280   
In Thread #2  multiply is 2240  
In Thread #1  number is 9   
In Thread #2  multiply is 20160 

我希望它如何

In Thread #1  number is 1   
In Thread #2  multiply is 1   
In Thread #1  number is 4   
In Thread #2  multiply is 4     
In Thread #1  number is 5
In Thread #2  multiply is 20    
In Thread #1  number is 2   
In Thread #2  multiply is 40    
In Thread #1  number is 7   
In Thread #2  multiply is 280   
In Thread #1  number is 8   
In Thread #2  multiply is 2240  
In Thread #1  number is 9   
In Thread #2  multiply is 20160 

我不想要带队列的方法......如果有人知道该怎么做,我想修改这段代码。

3 个答案:

答案 0 :(得分:2)

问题是System.out.println()在同步块之外,因此虽然评估已正确序列化,但打印结果可能会交换订单。

您可以做的是将System.out.println()打包到Runnable,将其传递给numbers(Runnable printer)multiply(Runnable printer),然后从同步方法中调用printer.run()

答案 1 :(得分:0)

替代解决方案是使用我在评论中提到的flush

            System.out.print("\nIn " + getName() + " number is " + array[i] + "\t");
            System.out.flush();

注意:有趣的是,在Eclipse IDE中,它在打印到控制台时是同步的,而在命令行上则没有(如果有人想测试它)。

答案 2 :(得分:0)

我认为无需使用您的Synchronize

您正在同步方法numbers()multiply(),因为根据您的锁main方法,两个线程不会调用这两个方法,除非此程序在外部多次启动。所以没有必要让它们成为同步的。

对于打印,替代只发生在每个线程类中的此语句Thread.sleep(1000)(并非所有时间,但有时),它不会一直打印,因为它依赖于第二个线程来完成其任务在其他主题的Thread.sleep()中提到的时间内。

如果您想尝试,可以在两个类

中注释这些行
   s.numbers()
   s.multiply()

仍然可以看到预期的输出至少一次,