Java如何同步2个线程?

时间:2015-12-05 11:40:57

标签: java multithreading synchronized

已解决!

我有一份功课。我很快就会说是什么。我必须从.txt文件中读取少量数字,并将它们相乘。我需要使用线程并仅同步该乘法。我已经这样做了,我的作业在这里结束了!但是,我想继续创建一个更复杂的方式,例如:

我有.txt这样的数字:5,6,2,11,24,10, 然后我将它们乘以5 * 6 * 2 * 11 * 24 * 10。

如何创建2个线程,Thread #1表示数字,Thread #2表示乘法,并在控制台中打印出来,如下所示:

Thread #1 running, number is 5
Thread #2 running, multiply is 5
Thread #1 running, number is 6
Thread #2 running, multiply is 30
Thread #1 running, number is 2
Thread #2 running, multiply is 60

我真的很感激任何建议,因为我工作了10个小时,但仍然无法让它发挥作用。

class MyThread extends Thread {
    Thread thread;

    MyThread(String name) {
        thread = new Thread(this, name);
    }

    public synchronized void numbers(boolean running) {
        if (!running) {
            notify();
            return;
        }
        notify();

        try {

            FileInputStream fs = new FileInputStream("in.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(fs));
            String line;
            int numbers = 0;

            while ((line = br.readLine()) != null) {
                String[] splitter = line.split("\\s");
                numbers = Integer.parseInt(splitter[0]);
                for (int i = 0; i <= splitter.length - 1; i++) {
                    numbers = Integer.parseInt(splitter[i]);
                    System.out.print("\nIn " + thread.getName() + "number is " + numbers + "\t");
                    Thread.sleep(500);
                }
            }
        } catch (InterruptedException e) {
            System.out.println("main thread interrupted");
        } catch (IOException e) {
            System.out.println("main thread interrupted");
        }
    }

    public synchronized void multiply(boolean running) {
        if (!running) {
            notify();
            return;
        }
        notify();

        try {
            FileInputStream fs = new FileInputStream("in.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(fs));
            String line;
            int numbers = 0;
            int multiply = 1;

            while ((line = br.readLine()) != null) {
                String[] splitter = line.split("\\s");
                numbers = Integer.parseInt(splitter[0]);
                for (int i = 0; i <= splitter.length - 1; i++) {
                    numbers = Integer.parseInt(splitter[i]);
                    multiply = multiply * numbers;
                    System.out.print("\nIn " + thread.getName() + " multiply is " + multiply + "\t");
                    Thread.sleep(500);
                }
            }
        } catch (InterruptedException e) {
            System.out.println("main thread interrupted");
        } catch (IOException e) {
            System.out.println("main thread interrupted");
        }
    }

    synchronized public void run() {
        if (thread.getName().compareTo("Thread #1 ") == 0) {
            for (int i = 0; i < 1; i++)
                this.numbers(true);
            this.numbers(false);
        } else {
            for (int i = 0; i < 1; i++)
                this.multiply(true);
            this.multiply(false);
        }
    }
}

我的代码如下:

主要是我打电话:

  MyThread mt1 = new MyThread("Thread #1 ");
  MyThread mt2 = new MyThread("Thread #2 ");
  mt1.start();
  mt2.start();

此时,我的输出看起来像这样:

In Thread #2  multiply is 5  
In Thread #1 number is 5    
In Thread #1 number is 6    
In Thread #2  multiply is 6  
In Thread #2  multiply is 30    
In Thread #1 number is 2    
In Thread #1 number is 11   
In Thread #2  multiply is 660   
In Thread #2  multiply is 15840  
In Thread #1 number is 24   

3 个答案:

答案 0 :(得分:2)

问题在于您尝试对两个任务使用一个实现。我建议创建ReadThread来读取输入文件和MultiplyThread,例如等待某个事件并乘以数字。他们还需要分享一些数字集合(例如,见ConcurrentLinkedQueue)。

所以ReadThread从文件中读取一个数字,将其添加到队列中。同时MultiplyThread等待出现在同一队列中的任何内容,当发生这种情况时,会将前一个上的新数字相乘。设计也会有所改进,因为我们不需要太多努力就可以用MultiplyThread来代替AddThread,而synchronized会计算数字的总和。

但是,您的实现尝试在一个类中执行这两项任务,这极大地增加了复杂性。还试图摆脱Thread.sleepReadThread语句,在你的情况下,它们会降低性能,使用多线程是没有意义的。

以下是我建议的方法的示例实现。

首先是class ReadThread implements Runnable { private final String filename; private final ConcurrentLinkedQueue<Integer> queue; public ReadThread(ConcurrentLinkedQueue<Integer> queue, String filename) { this.queue = queue; this.filename = filename; } public void run() { try { FileInputStream fs = new FileInputStream(filename); Scanner scanner = new Scanner(fs); while (scanner.hasNextInt()) { int number = scanner.nextInt(); System.out.println("ReadThread read " + number); queue.add(number); } } catch (FileNotFoundException e) { e.printStackTrace(); } } } 。它具有包含必须处理的数字的队列。我已经简化了文件中数字的读取,你可以用读取实现来替换它。

MultiplyThread

result。这里我们从队列中取出数字并将其乘以存储前一个值的active。线程生命周期存在问题 - 我们不知道何时应该停止它。所以我使用了简单的class MultiplyThread implements Runnable { private boolean active = true; private Integer result = 1; private final Queue<Integer> queue; public MultiplyThread(ConcurrentLinkedQueue<Integer> queue) { this.queue = queue; } public void run() { while (isActive()) { Integer number = queue.poll(); if (number != null) { result *= number; System.out.println("MultiplyThread current result is " + result); } } } public synchronized void stop() { active = false; } public synchronized boolean isActive() { return active; } } 标志。这告诉线程何时停止。

MultiplyThread

这是最后一部分。由于public static void main(String[] args) throws InterruptedException { ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>(); ReadThread readThread = new ReadThread(queue, "numbers.txt"); MultiplyThread multiplyThread = new MultiplyThread(queue); Thread reader = new Thread(readThread); Thread multiplicator = new Thread(multiplyThread); multiplicator.start(); reader.start(); reader.join(); multiplyThread.stop(); multiplicator.join(); } 中断,它比你的更复杂。

ReadThread read 1
ReadThread read 2
MultiplyThread current result is 1
MultiplyThread current result is 2
ReadThread read 3
MultiplyThread current result is 6
ReadThread read 4
MultiplyThread current result is 24
ReadThread read 5
MultiplyThread current result is 120
ReadThread read 6
MultiplyThread current result is 720
ReadThread read 7
MultiplyThread current result is 5040

程序的结果

ReadThread

您可以看到该线程同时工作,MultiplyThread不等待addFilter()计算所有先前值的结果。

答案 1 :(得分:0)

目前尚不清楚你要做什么。代码中有一些明显的错误,我想突出显示(因此写下这个答案),但是我无法回答这个问题,因为代码似乎做了写的事情:它运行2个线程,两个都读取相同的文件和输出结果以略微不同的方式阅读。

现在问题:

1)如果你正在扩展Thread,你不应该有一个线程字段。基本上你可以替换thread = new Thread(this,name);超级(姓名)。

2)你的同步没有做任何事情。当您输入方法时,Synchronized make方法进入监视器(基本上获取对象锁定),并在方法完成时释放它。你的两个线程是两个不同的实例,彼此之间没有数据,所以同步没有做任何事情。

答案 2 :(得分:0)

您编写代码的方式,这两个线程并非真正“连接”,它们并不共享任何内存。他们读了两个相同的文件,但这都是 - 没有共享内存。根据我的猜测,这个想法宁愿有一个生产者&#34;从文件读取数据的线程,以及&#34;消费者&#34;获取第一个线程读取的数据并执行乘法的线程。第二个线程不应该读取文件。

你可以用共享的AtomicInteger写一些东西:当为空(null)时,&#34;生产者&#34;线程将其设置为已读取的内容;当非空时,&#34;消费者&#34;线程读取它,将其重置为空,并可以运行它的乘法。