多线程程序无法正确完成工作?

时间:2019-03-08 19:00:45

标签: java multithreading

因此,就像问题图块一样。我正在尝试学习多线程编程。我有一个尴尬的程序使我理解多线程比常规执行更快。该程序在一个Java文件中具有七个类,一个测试类,三个实现Runnable的类,以及三个常规类。六个类都执行相同的操作,计数到1000万并返回结果。我的问题是使用三个线程来运行的三个类,但是它们没有返回我期望的正确计数。但是,三个常规班都可以。

我真的很感谢任何人都可以帮助我了解它发生的原因!我使用JDK 9和Eclipse 2018-12。

import java.time.Duration;
import java.time.Instant;

class MyMultiThreadExample{

    public static void main(String[] args) {

        GameOne g1 = new GameOne();
        GameTwo g2 = new GameTwo();
        GameThree g3 = new GameThree();

        Thread thread1 = new Thread(g1);
        Thread thread2 = new Thread(g2);
        Thread thread3 = new Thread(g3);

        Instant start1 = Instant.now();

        thread1.start();

        thread2.start();

        thread3.start();

        Instant end1 = Instant.now();

        long elapsed = Duration.between(start1, end1).toMillis();

        int total = g1.getCount() + g2.getCount() + g3.getCount();

        System.out.println("MultiThread running cost " + elapsed + " to count " + total + " times");

        GameFour g4 = new GameFour();
        GameFive g5 = new GameFive();
        GameSix g6 = new GameSix();

        Instant start2 = Instant.now();

        g4.run();
        g5.run();
        g6.run();

        Instant end2 = Instant.now();

        long elapsed2 = Duration.between(start2, end2).toMillis();

        int total2 = g3.getCount() + g4.getCount() + g5.getCount();

        System.out.println("Sequential running cost " + elapsed2 + " to count " + total2 + " times");
    }

}

class GameOne implements Runnable {

    int count1 = 0;

    @Override
    public void run() {

        for (int i = 0; i < 10000000; i++) {
            // System.out.print("Game1 at round " + count + " now");
            count1++;
        }
    }

    public int getCount() {
        System.out.println("GameOne counts " + count1);
        return count1;
    }
}

class GameTwo implements Runnable {

    int count2 = 0;

    @Override
    public void run() {

        for (int i = 0; i < 10000000; i++) {
            // System.out.print("Game2 at round " + count + " now");
            count2++;
        }
    }

    public int getCount() {
        System.out.println("GameTwo counts " + count2);
        return count2;
    }
}

class GameThree implements Runnable {

    int count3 = 0;

    @Override
    public void run() {

        for (int i = 0; i < 10000000; i++) {
            // System.out.print("Game3 at round " + count + " now");
            count3++;
        }
    }

    public int getCount() {
        System.out.println("GameThree counts " + count3);
        return count3;
    }
}

class GameFour {

    int count4 = 0;

    public void run() {

        for (int i = 0; i < 10000000; i++) {
            // System.out.print("Game3 at round " + count + " now");
            count4++;
        }
    }

    public int getCount() {
        System.out.println("GameFour counts " + count4);
        return count4;
    }
}

class GameFive {

    int count5 = 0;

    public void run() {

        for (int i = 0; i < 10000000; i++) {
            // System.out.print("Game3 at round " + count + " now");
            count5++;
        }
    }

    public int getCount() {
        System.out.println("GameFive counts " + count5);
        return count5;
    }
}

class GameSix {

    int count6 = 0;

    public void run() {

        for (int i = 0; i < 10000000; i++) {
            // System.out.print("Game3 at round " + count + " now");
            count6++;
        }
    }

    public int getCount() {
        System.out.println("GameFive counts " + count6);
        return count6;
    }
}

2 个答案:

答案 0 :(得分:0)

您忘了调用thread.join()了-这要等到线程完成执行为止。

否则,您正在执行中间读取counter

您的代码应为:

thread1.start()
thread2.start()
thread3.start()

thread1.join()
thread2.join()
thread3.join()

此外,您所有的类都可以压缩为一个class Game

class Game implements Runnable {
    String name;
    int count = 0;

    public Game(String name) {
        this.name = name;
    }

    @Override
    public void run() {

        for (int i = 0; i < 10000000; i++) {
            // System.out.print(name + " at round " + count + " now");
            count++;
        }
    }

    public int getCount() {
        System.out.println(name + " counts " + count);
        return count;
    }
}

每个都有自己的计数器,您可以通过调用run()在一个线程或同一线程中运行它们-您的main方法除实例化之外,大部分保持不变。可以像这样实例化它们:

Game g1 = new Game("GameOne");
Game g2 = new Game("GameTwo");
Game g3 = new Game("GameThree");
Game g4 = new Game("GameFour");
Game g5 = new Game("GameFive");
Game g6 = new Game("GameSix");

答案 1 :(得分:0)

  

我有一个尴尬的程序让我理解多线程比常规执行更快。

重要的是要了解并非总是如此。只有长时间运行的任务可以并行运行时,才应使用多个线程。如果您的任务很短,则几乎可以肯定,通过在单个线程上运行,它们会更快地运行,因为在线程之间创建专门的同步会产生开销。

这样一来,您实际上并没有在此处测量正确的时间。

调用Thread.start()时,它将与函数中的代码并行运行相关的Runnable

要让线程继续运行直到完成,必须调用Thread#join()

thread1.start();
thread2.start();
thread3.start();

// all 3 Threads may be running now, but maybe not even started!
// let's wait for them to finish running by joining them
thread1.join();
thread2.join();
thread3.join();

这是最简单的等待方式...但是还有其他一些,这是一个复杂的话题。

您还可能会遇到麻烦,因为您的任务处于可变状态(count变量),并且需要仔细管理来自不同线程的更改的可见性(例如,您可以使其变得易变,因此更新是刷新到其他线程。

要了解有关Java并发的更多信息,建议您阅读有关它的内容。 Baeldung教程非常出色。