简体   繁体   English

Java并行同步2个线程

[英]Java synchronize 2 threads in parallel

-----------------SOLVED , Thank you for your suggestions ! -----------------已解决,谢谢您的建议! ------------ ------------

I have the following code where I have an array of numbers. 我有以下代码,其中有一个数字数组。 I want to create 2 threads who execute in parallel. 我想创建2个并行执行的线程。 First thread to print number value and second thread multiply. 第一线程打印数字值,第二线程乘以。 Here is my code 这是我的代码

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();
    }
}

Code output is like: 代码输出如下:

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 

How I want it to be 我希望它成为

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 

I don't want method with queue... I would like just to modify this code if anyone know how to do. 我不想要带有队列的方法...如果有人知道怎么做,我只想修改这段代码。

The problem is System.out.println() is outside of synchronization block and therefore although evaluation is correctly serialized, printing the results may swap the order. 问题是System.out.println()在同步块之外,因此尽管评估已正确序列化,但打印结果可能会交换顺序。

What you can do is to wrap System.out.println() into Runnable , pass it to numbers(Runnable printer) and multiply(Runnable printer) and call the printer.run() from within the synchronized methods. 您可以做的是将System.out.println()包装到Runnable ,将其传递给numbers(Runnable printer)multiply(Runnable printer)然后从同步方法中调用printer.run()

Alternative solution is to use flush as I mentioned in comment. 如我在评论中提到的,替代解决方案是使用flush

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

Note: it is interesting, that in Eclipse IDE it was synchronized when printed to console and on command line it was not (if someone wants to test it). 注意:有趣的是,在Eclipse IDE中,当打印到控制台时它是同步的,而在命令行上则不是(如果有人想对其进行测试)。

I see no need of using your Synchronize class 我认为不需要使用您的Synchronize

you are synchronizing methods numbers() and multiply() where as these two methods will not be called by two threads as per your lock main method until unless this program started externally more than once. 您正在同步方法numbers()multiply() ,因为按照锁main方法,这两个方法将不会被两个线程调用,除非该程序在外部多次启动。 So no point of making them as synchronized. 因此,使其同步是没有意义的。

For the printing alternatively is only happening by this statement Thread.sleep(1000) in each thread class (Not all the times but some times), it wont print all the times alternatively as its depends upon the second thread to complete its task within mentioned time in Thread.sleep() of other thread. 因为仅在每个线程类中此语句Thread.sleep(1000) (不是所有时间,而是某些时候)才进行打印,所以它不会一直打印,因为它依赖于第二个线程来完成上述任务其他线程的Thread.sleep()的时间。

if you want to try, you can comment these lines in both the classes 如果您想尝试,可以在两个类中注释这些行

   s.numbers()
   s.multiply()

still you can see the expected output at least once, 您仍然至少可以看到一次预期的输出,

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM