【问题标题】:Threads related program not working线程相关程序不起作用
【发布时间】:2015-06-22 17:15:37
【问题描述】:

我正在尝试为线程运行以下程序,并期望变量对象应该由两个不同的线程更新。很奇怪,它只是显示值“加法-1”和“乘法-2”。但是当我使用调试器并逐步调试它时,“加法”和乘法就会按预期发生。如果我将“Thread.sleep”放在“P”的“运行”方法中 1000 毫秒。它工作正常。我已经注释掉了'Thread.sleep'的代码,但是如果你取消注释并运行它,你会发现预期的结果。谁能给我解释一下?

public class TestingThreads {   

    public static void main(String[] args) {

        Variable b = new Variable();
        Thread tp = new Thread(new P(b));
        Thread tq = new Thread(new Q(b));
        tp.start();
        tq.start();
        try {
            tp.join();
            tq.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

class Variable {
    int i = 0;
    boolean on = true;

    public synchronized void addition() {
        if (!on) {
            try {
                wait();
            } catch (InterruptedException e) {

                e.printStackTrace();
            }

        }
        i = i + 1;
        on=false;
        notify();
        System.out.println("addition " + i);



    }

    public synchronized void multiply() {

        if (on) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
        i = i * 2;
        on=true;
        notify();
        System.out.println("multiply " + i);

    }

}

class P implements Runnable {

    Variable b;

    P(Variable b) {
        this.b = b;
    }


    @Override
    public void run() {


        while (true) {
            /*uncomment it and it will work fine.*/

            /*try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }*/

            b.addition();

        }
    }

}

class Q implements Runnable {

    Variable b;

    Q(Variable b) {
        this.b = b;
    }

    @Override
    public void run() {

        while (true) {

            b.multiply();
        }
    }
}

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    您正在达到整数的顶部并环绕。查看每个操作的前后值:

    addition pre: 0
    addition post: 1
    multiply pre: 1
    multiply post: 2
    addition pre: 2
    addition post: 3
    multiply pre: 3
    multiply post: 6
    addition pre: 6
    addition post: 7
    multiply pre: 7
    multiply post: 14
    addition pre: 14
    addition post: 15
    multiply pre: 15
    multiply post: 30
    addition pre: 30
    addition post: 31
    multiply pre: 31
    multiply post: 62
    addition pre: 62
    addition post: 63
    multiply pre: 63
    multiply post: 126
    addition pre: 126
    addition post: 127
    multiply pre: 127
    multiply post: 254
    addition pre: 254
    addition post: 255
    multiply pre: 255
    multiply post: 510
    addition pre: 510
    addition post: 511
    multiply pre: 511
    multiply post: 1022
    addition pre: 1022
    addition post: 1023
    multiply pre: 1023
    multiply post: 2046
    addition pre: 2046
    addition post: 2047
    multiply pre: 2047
    multiply post: 4094
    addition pre: 4094
    addition post: 4095
    multiply pre: 4095
    multiply post: 8190
    addition pre: 8190
    addition post: 8191
    multiply pre: 8191
    multiply post: 16382
    addition pre: 16382
    addition post: 16383
    multiply pre: 16383
    multiply post: 32766
    addition pre: 32766
    addition post: 32767
    multiply pre: 32767
    multiply post: 65534
    addition pre: 65534
    addition post: 65535
    multiply pre: 65535
    multiply post: 131070
    addition pre: 131070
    addition post: 131071
    multiply pre: 131071
    multiply post: 262142
    addition pre: 262142
    

    ...

    multiply pre: 1073741823
    multiply post: 2147483646
    addition pre: 2147483646
    addition post: 2147483647
    multiply pre: 2147483647
    multiply post: -2
    addition pre: -2
    addition post: -1
    multiply pre: -1
    multiply post: -2
    addition pre: -2
    

    睡眠也会发生同样的事情,只是要慢得多。 :)

    【讨论】:

    • 非常感谢您的回答,很好,我想在达到 int 值的最大值之前我无法看到。无论如何,如果您知道在运行后立即检查它。
    • 我看到了很多输出,所以开始在命令行上运行,并通过head(在 cygwin 或 linux 上)进行管道传输。这仅显示输出的前几行:java TestingThreads | head 将显示 addition pre: 0 addition post: 1 multiply pre: 1 multiply post: 2 addition pre: 2 addition post: 3 multiply pre: 3 multiply post: 6 addition pre: 6 addition post: 7 您也可以尝试使用 java TestingThreads > out.log 将所有输出通过管道传输到文本文件中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多