Java线程问题

Java线程问题,java,Java,我正在上Java课程。我们现在进入线程。这是我第一次体验多线程,所以如果问题非常愚蠢,请原谅:) 我有以下计划: public class Foo extends Thread { private int x = 2; public static void main(String[]args) { new Foo().fun(); } Foo () { x = 5; start(); } pub

我正在上Java课程。我们现在进入线程。这是我第一次体验多线程,所以如果问题非常愚蠢,请原谅:)

我有以下计划:

public class Foo extends Thread {
    private int x = 2;

    public static void main(String[]args) {
        new Foo().fun();
    }

    Foo () {
        x = 5;
        start();
    }

    public void fun() {
        x = x - 1;
        System.out.println(x);
    }
    public void run() {
        x = x * 2;
    }
}

当我运行程序时,我得到4作为输出。上述程序的输出是否始终为4?

是,它将始终为4。我看不出它没有理由不是
4

您只运行
fun()
,从不运行
run()


阅读

是的,它将始终是4。我看不出它没有理由不是
4

您只运行
fun()
,从不运行
run()


阅读

它并不总是4

如果Foo run()方法在主线程运行fun()之前执行,则它将是9

如果Foo run()方法在main运行fun()时执行,则它将为8


如果main()在Foo启动之前完成,它将是4,但并不总是4

如果Foo run()方法在主线程运行fun()之前执行,则它将是9

如果Foo run()方法在main运行fun()时执行,则它将为8


如果main()在Foo启动之前完成,则它将是4,但并不总是如此。因为在调用
start()
方法时,从主线程调用
fun
和从
thread.start调用
run
之间存在竞争条件,这将改变
x
的值


但是,实际上,如果没有适当的同步,就无法保证输出是什么,与调用
fun
run
的顺序无关。因为同步确保了线程更改的可见性,所以即使
run
将在调用
fun
之前完成,输出也可以是4。

不,不总是这样。因为在调用
start()
方法时,从主线程调用
fun
和从
thread.start调用
run
之间存在竞争条件,这将改变
x
的值


但是,实际上,如果没有适当的同步,就无法保证输出是什么,与调用
fun
run
的顺序无关。因为同步可以确保线程更改的可见性,所以即使在调用
fun
之前
run
将完成,输出也可以是4。

正如您所说,您正在学习多线程,您必须知道,您永远无法预测不同线程的执行顺序

这是一个非常简单的程序,其中主线程几乎总是首先完成,但要记住的重要一点是,在复杂的多线程场景中,您永远无法确定。事实上,在一个线程不依赖于另一个线程的执行的情况下,您选择了多线程方法

顺便说一句,请尝试以这种方式更改构造函数:

Foo () {
        x = 5;
        start();
        Thread.sleep(2 * 1000);
    }

您可能会得到不同的结果。

正如您所说,您正在学习多线程,您必须知道,您永远无法预测不同线程的执行顺序

这是一个非常简单的程序,其中主线程几乎总是首先完成,但要记住的重要一点是,在复杂的多线程场景中,您永远无法确定。事实上,在一个线程不依赖于另一个线程的执行的情况下,您选择了多线程方法

顺便说一句,请尝试以这种方式更改构造函数:

Foo () {
        x = 5;
        start();
        Thread.sleep(2 * 1000);
    }


您可能会得到不同的结果。

是正确的,但需要注意。Java有一些变量值的缓存。如果变量未设置为volatile或未使用原子值,则可能会获取缓存的值,而不是最新的值。

是正确的,但需要注意。Java有一些变量值的缓存。如果变量未设置为volatile或未使用原子值,则可能会获取缓存的值,而不是最新的值。

但构造函数正在调用start,该函数调用run。实例化
线程
,没有什么特殊的操作,只需像常规类一样调用
new
。您引用的Javadoc也给出了一个例子。但是构造函数调用start调用run。要实例化
线程
,没有什么特别的事情要做,只需像普通类一样调用
new
。您引用的Javadoc也展示了一个例子。谢谢你能解释一下“8作为输出”部分吗?我明白了。如果x=x*2发生在x=5之后但在打印之前。我说得对吗?值得注意的是,由于线程是在构造函数中启动的,因此线程可以将
x
视为5、2或0(或者在fun()启动后启动4)Peter,你能详细说明一下吗?如果
run
fun
的第一行之前读取
x
,并在
fun
的两行之间将其双精度写回
x
,那么输出将是5*2=10.5。谢谢你能解释一下“8作为输出”部分吗?我明白了。如果x=x*2发生在x=5之后但在打印之前。我说得对吗?值得注意的是,由于线程是在构造函数中启动的,因此线程可以将
x
视为5、2或0(或者在fun()启动后启动4)Peter,您能详细说明一下吗?如果
run
fun
的第一行之前读取
x
,并将其双精度写回
x
fun
的两行之间,那么输出将是5*2=10。谢谢您的先生。这个网站太快了:)谢谢你的先生。这个网站太快了:)我的文本有这个在练习中,但没有作业。我的文本有这个在练习中,但没有作业。