2013-02-26 109 views
4

说我有:Java的运行和停止线程

class WriteThread extends Thread { 
    char letter; 
    boolean stop = false; 
    WriteThread(char letter) { 
     this.letter = letter; 
    } 
    public void halt() { stop = true; } 
    public void run() { 
     while(!stop) { System.out.print(letter); } 
    } 
} 

和:

WriteThread a = new WriteThread('a'); 
WriteThread b = new WriteThread('b'); 
a.start(); 
b.start(); 
// do some other stuff 
a.halt(); 
b.halt(); // (*) 

都是线程保证时(*)中,停止? (通过停止,我的意思是在(*)之后将不再有打印)

+2

没有,因为你有多个线程“后”。 你也应该声明停止为易变 – cIph3r 2013-02-26 00:47:46

+0

*“将不会再打印(*)”*之后,可能。 – MadProgrammer 2013-02-26 00:47:47

+0

@MadProgrammer为什么可能?因为止损不是挥发性的? – Shmoopy 2013-02-26 00:51:24

回答

4

您需要使'stop'变量变为volatile。当线程看到该值为真时,线程将停止循环,但可能会有输出缓冲,这会混淆问题。

+0

我认为这里最重要的问题不在于“停止”是否波动。即使'stop'也是不稳定的,即使在stdout中没有缓冲,在上一次暂停之后仍然可以看到输出。请看我的答案。 – 2013-02-26 03:01:19

0

除了使“stop”变量易变,为了让你的代码更“线程安全”,你应该为“stop”添加同步的get/set方法并使用它们(在while循环中“get”和“set “在”停止“方法内)。

尽管如此,您仍不能保证线程在“停止”后停止,但您可能会看到较少的“打印”。

要得到这样的保证,您必须使用某种“线程同步”机制(例如Semaphore),以调用“a.halt()”的线程指示“a”线程停止“而“循环并停止(内部暂停),直到”while“循环有效结束并”释放“信号量(以便调用线程继续执行)。

1

当然不是。它与易失性无关,它仅仅是多线程的本质。

在你调用a.halt()之后,线程a可能不会被授予任何继续执行的机会,并且你的主线程执行b.halt()。之后,线程a可能仍然在您的println声明之前的位置。

只是一个简化版本将展示:

MAIN THREAD    THREAD A 
          while (!stop) 
a.halt() 
          println(...) 

后你叫a.halt()a仍然有机会继续打印,即使stop变量波动。

为了确保一个线程一定点完之后,请使用join()方法:

WriteThread a = new WriteThread('a'); 
WriteThread b = new WriteThread('b'); 
a.start(); 
b.start(); 
// do some other stuff 
a.halt(); 
b.halt(); 
a.join(); 
b.join(); 
// a and b are guaranteed to have finished at this point