我有以下代码。
public class Test implements Runnable
{
static int id = 0;
int value = 0;
public static int getId() {
return ++id;
}
public static void main(String[] args)
{
Test t = new Test();
t.value = 10;
new Thread(t, "child " + getId()).start();
new Thread(t, "child " + getId()).start();
t.value = 20;
new Thread(t, "child " + getId()).start();
new Thread(t, "child " + getId()).start();
}
@Override
public void run() {
System.out.println("Thread " + Thread.currentThread().getName() + " started");
System.out.println(Thread.currentThread().getName() + " Data - " + this.value);
}
}
样品运行时的输出:
Thread child 1 started
Thread child 2 started
child 2 Data - 20
child 1 Data - 20
Thread child 3 started
child 3 Data - 20
Thread child 4 started
child 4 Data - 20
我可以看到线程对象的(测试)最新数据反映在所有线程中。但是如何?
我期望在t.value=20
行之前启动并执行的线程应具有数据值' 10'。我错了吗?
答案 0 :(得分:0)
new Thread(t, "child " + getId()).start();,
并不意味着,此时启动了新的Thread。它可能需要一些时间才能开始。 如果要等待它,可以将其提取到变量。
Thread t=new Thread(t, "child " + getId());
t.start();
并等待它完成:t.join()
同样打印值为20的数据很幸运,因为您的程序不是线程安全的。在您的示例中,您应该在值之前使用至少volatile关键字。
volatile int value = 0;
答案 1 :(得分:0)
为所有线程传入相同的Runnable
对象,以便共享变量value
。您看到的值取决于执行线程的顺序。如果主线程(创建其他线程的线程)首先完成,您将看到此结果。
答案 2 :(得分:0)
创建线程时,您传递的是相同的Runnable
,即t
。因此,所有线程都有效地使用相同的value
。
Thread.start()
不保证任何特定排序。线程可以稍早或稍晚开始。当线程有机会运行时,主线程可能已经将value
设置为20。
作为旁注:您正在使用没有任何同步的共享变量。您应该使用volatile
或synchronized
来获得可预测的结果。