Java如何同步2个线程?

标签 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   

最佳答案

问题是您尝试使用一种实现来完成这两项任务。我建议创建 ReadThread 来读取输入文件,并创建 MultiplyThread 来等待某些事件,例如乘以数字。他们还需要共享一些数字集合(例如,参见 ConcurrentLinkedQueue)。

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

但是,您的实现尝试在一个类中完成这两项任务,这会大大增加复杂性。还要尝试摆脱 synchronizedThread.sleep 语句,在您的情况下,它们会降低性能,并且使用多线程没有意义。

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

首先是ReadThread。它有一个队列,其中包含必须处理的数字。我已经简化了从文件中读取数字的过程,您可以将其替换为您的读取实现。

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。在这里,我们从队列中取出数字并将其乘以存储先前值的结果。线程生命周期存在问题——我们不知道什么时候应该停止它。所以我使用了简单的 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 计算所有先前值的结果。

关于Java如何同步2个线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34104439/

相关文章:

java - DelayQueue 意外行为。 DrainTo 仅从队列中删除 1 个过期项

Java 线程和同步块(synchronized block)

jvm - 有没有独立的 JAVA 可以在没有任何操作系统的 PC 上运行

java - 使用 @Configuration 时出现 NoSuchBeanDefinitionException

java - <c :choose> not working in datatable

java - 通过同步块(synchronized block)获取对象的锁

java - Java生产者使用者问题中使用Atomic Integer的奇怪输出

java - 抽象父类(super class)中实现的超接口(interface)方法的方面

java - 同步 arrayList- 不兼容的类型

Java - 'synchronized' 和 'final' 方法,声明顺序