使以下线程无法预测地运行。有时它可能会打印ABC和其他123.我不明白为什么它能够打印ABC。请解释其执行流程。
public class ArrayDeclaration implements Runnable {
String [] s;
public ArrayDeclaration (String []s){
this.s=s;
}
public void run() {
synchronized (this){
try
{
wait(5000);
System.out.print(s[0]+s[1]+s[2]);
}
catch(InterruptedException ie){
}
}
}
}
/**
* @param args the command line arguments
*/class Test{
public static void main(String[]args)throws Exception {
String[] s = new String []{"1","2","3"};
ArrayDeclaration myRunnable = new ArrayDeclaration(s);
// TODO code application logic here
Thread t1 = new Thread(myRunnable);
t1.start();
t1.join(5000);
s[0]="A";
s[1]="B";
s[2]="C";
}
}
我没有得到String数组的范围。为什么(有时)改为ABC并打印?这些变化不应该只影响其主要范围吗?此行为是否与字符串池有关?
答案 0 :(得分:2)
它能够做到这一点,因为加入调用的超时与ArrayDeclaration中相同长度的等待相结合。所以,你启动线程,立即进行等待(5000)。您加入的最高可达5000毫升。等待和连接都完全接近于一个线程或另一个线程可能获得下一个时间片执行的同一时刻,具体取决于许多外部因素。在某些情况下,主线程获得第一次机会,因此它在另一个线程打印它们之前设置数组成员。在其他情况下,打印线程获得第一次机会。
如果加入和等待的长度不同,那就更容易预测了。
答案 1 :(得分:1)
两个定时器wait
和join
都有5000毫秒的参数,因为计算机时钟通常具有大约30毫秒的分辨率,两个定时器几乎同时耗尽,因此无法预测什么首先发生,等待后的代码或加入后的代码。
将要加入的参数更改为6000毫秒将确保线程可以运行其路线并导致成功join
并始终打印123
。
答案 2 :(得分:0)
首先,你在线程中等待5秒,你也加入最长等待时间为5秒。
时间很难,API无法保证准确的时间安排。所以我认为有时连接实际等待4998毫秒而wait()是5002毫秒,此时阵列已经改变。当然不总是,有时反过来然后打印123。 (提及时代就是一个例子)。
您可以通过使用join()而不会超时来获得sequantial流。
答案 3 :(得分:0)
加入时的超时在等待超时之前到期。即使它们都设置为相同的等待间隔,无论哪个线程首先运行并且其超时到期都将是相当随机的。因此导致在打印发生之前,在连接首先到期的随机情况下更改数组内容。