【问题标题】:Multithreading Application won't run after JUnit Test多线程应用程序在 JUnit 测试后不会运行
【发布时间】:2018-03-14 18:44:18
【问题描述】:

我的打印机柜台学校问题有问题。它应该是一个多线程应用程序,到目前为止运行良好。但是当我第二次或第三次运行它时,它不再起作用了。没有错误消息。看起来线程永远睡着了。此外,当我使用 JUnit 测试对其进行测试时,它也不起作用。但有时它确实......这本身就很奇怪。

public class CounterPrinter {


public static void main(String[] args) throws InterruptedException {
    if (args.length != 2) {
        System.out.println("Usage: CounterPrinter <min> <max>");
        System.exit(1);
    }
    Storage s = new Storage();
    Printer d = new Printer(s, Integer.parseInt(args[1]));
    Counter z = new Counter(s, Integer.parseInt(args[0]), Integer.parseInt(args[1]));

    z.start();
    d.start();

    z.join();
    d.join();


    Thread.sleep(5000);

}

}



public class Printerextends Thread {
private Storage storage;
private Integer ende;


Printer(Storage s, Integer ende) {
    this.storage = s;
    this.ende = ende;
}


@Override
public void run() {
    while (storage.hasValue()) {
        try {

            System.out.print(speicher.getValue(ende) + " ");
            Thread.sleep(50);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


}

}

public class Counter extends Thread {
private Storage speicher;
private int max, min;

Counter(Storages, int min, int max) {
    this.storage = s;
    this.max = max;
    this.min = min;
}


@Override
public void run() {
    for (int i = min; i <= max; i++) {
        try {
            storage.setValue(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

}


public class Storage implements StorageIf {
private Integer wert;
private boolean hasValue = false;

@Override
public synchronized Integer getValue(Integer ende) throws InterruptedException {
    if(wert.equals(ende)){
        hasValue = false;
        return wert;
    }else {
        while (!hasValue()) {
            wait();
        }

        hasValue = false;
        notifyAll();
        return wert;
    }
}


@Override
public synchronized void setValue(Integer wert) throws InterruptedException {
    while (hasValue()){
        wait();
    }
    hasValue = true;
    this.wert = wert;
    notifyAll();

}


@Override
public boolean hasValue() {
    return hasValue;
}
}

希望有人能发现我犯的错误:(

非常感谢!!!

【问题讨论】:

  • 通过调试尝试点击“暂停”按钮并通过检查它们的堆栈跟踪来查看线程结束的位置...
  • 如果某些多线程的东西有时能工作有时不能,你可以打赌这将是一个同步问题。
  • 这个多线程应用程序应该做什么?
  • 因此 Counter 类应该将一个值从 1 增加到 50 并在存储对象中的每个增量后存储它。打印机类应该获取存储值并单独打印每个数字。调试时,我有时会看到我的主线程在等待...不知道如何找出同步问题:(
  • Storage boolean hasValue 不是 volatile 且 Storage hasValue( ) 方法不同步。所以当 Printer 在它的存储对象上调用 hasValue() 时,它可能看不到 hasValue 的当前值,从而可能导致线程明显挂起。

标签: java multithreading intellij-idea junit


【解决方案1】:

问题在于您将两种状态混为一谈:

  • 当前有可用值
  • 将不再有值

hasEnded() 方法添加到您的存储类,检查是否已达到最终值。确保同步此方法以及hasValue() 方法。读写访问都需要同步!

然后让Printer 的while 循环检查hasEnded,而不是hasValue

最后:摆脱所有sleep() 调用。

您自己的答案,解决睡眠问题,并不是真正的解决方案。线程安全程序不依赖于计算机的性能才能正常运行。

【讨论】:

    【解决方案2】:
        z.start();
        z.sleep(100);
        d.start();
    

    在启动两个线程之间设置延迟为我解决了这个问题。在启动 Thread d 之前,我的电脑在 Thread z 中的运行速度可能太快了。这就是为什么它有 50% 的时间会自行挂断。

    谢谢大家 :)

    【讨论】:

      猜你喜欢
      • 2018-02-09
      • 2016-07-30
      • 2013-12-08
      • 1970-01-01
      • 1970-01-01
      • 2015-05-27
      • 1970-01-01
      • 1970-01-01
      • 2020-03-25
      相关资源
      最近更新 更多