Java 多线程应用程序赢得';在JUnit测试之后不运行

Java 多线程应用程序赢得';在JUnit测试之后不运行,java,multithreading,intellij-idea,junit,Java,Multithreading,Intellij Idea,Junit,我的打印机柜台出了问题。它应该是一个多线程应用程序,目前运行良好。但是当我第二次或第三次运行它时,它就不再工作了。。没有错误消息。看起来好像睡了很久。而且,当我用JUnit测试它时,它也不会工作。但有时它确实。。。威奇本身已经很奇怪了 public class CounterPrinter { public static void main(String[] args) throws InterruptedException { if (args.length != 2) {

我的打印机柜台出了问题。它应该是一个多线程应用程序,目前运行良好。但是当我第二次或第三次运行它时,它就不再工作了。。没有错误消息。看起来好像睡了很久。而且,当我用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;
}
}
公共类计数器{
公共静态void main(字符串[]args)引发InterruptedException{
如果(参数长度!=2){
System.out.println(“用法:套印机”);
系统出口(1);
}
存储s=新存储();
打印机d=新打印机(s,Integer.parseInt(args[1]);
计数器z=新计数器(s,Integer.parseInt(args[0]),Integer.parseInt(args[1]);
z、 start();
d、 start();
z、 join();
d、 join();
睡眠(5000);
}
}
公共类Printerextends线程{
专用存储;
私有整数ende;
打印机(存储器s、整数ende){
这个存储=s;
this.ende=ende;
}
@凌驾
公开募捐{
while(storage.hasValue()){
试一试{
System.out.print(speicher.getValue(ende)+“”);
睡眠(50);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
}
公共类计数器扩展线程{
私人存储空间;
私有整数最大值,最小值;
计数器(存储、最小整数、最大整数){
这个存储=s;
this.max=max;
this.min=min;
}
@凌驾
公开募捐{
对于(int i=min;i
在启动两个线程之间设置一个延迟,解决了我的问题。我的计算机在启动线程d之前,可能在线程z中运行得太快了。这就是为什么它在50%的时间内挂断自己


多亏了大家(tho:)

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

  • 当前有一个可用的值
  • 将不会有更多的值
hasEnded()
方法添加到存储类中,检查是否已达到结束值。确保同步此方法以及
hasValue()
方法。同步需要在读写访问上都完成

然后在循环检查
hasend
,而不是
hasValue
时进行
Printer

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


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

调试时,请尝试点击“暂停”按钮,通过检查线程的堆栈跟踪来查看线程的最终位置…如果某个多线程有时有效,有时无效,您可以打赌这将是一个同步问题。这个多线程应用程序应该做什么?因此计数器类应该将值从1增加到50,并在e之后存储它存储对象中的增量非常大。Printer类应该获取存储值,并单独打印每个数字。在解除Bug时,我有时会看到我的主线程处于等待状态…不知道如何解决同步问题:(存储布尔值hasValue不是易失性的,存储hasValue()方法未同步。因此,当打印机在其存储对象上调用hasValue()时,它可能看不到hasValue的当前值,因此可能会导致线程明显挂起。
    z.start();
    z.sleep(100);
    d.start();