今天看Java一個關於多線程返回值方式的示例,發現一個本身不太能理解的問題,就是在主線程中啓動了幾個工做線程,主線程中也沒有join,工做線程竟然也是正常輸出了回調的結果。這個跟linux C++下的線程知識但是不同的,在C++下,若是main函數退出了,那麼全部的子線程也就退出了,我一開始懷疑是否是書上寫的不夠仔細,沒有測試,因此本身寫了幾個類簡單的測試了一下。代碼以下:java
ThreadCallback.java代碼:linux
package thread.callback; public class ThreadCallback { public void callBack(String msg) { System.out.println(msg); } }
WorkThread.java代碼:多線程
package thread.callback; public class WorkThread extends Thread{ private ThreadCallback callback; private String threadName; public WorkThread(ThreadCallback _callback, String _threadName) { // TODO Auto-generated constructor stub this.callback = _callback; this.threadName = _threadName; } @Override public void run() { // TODO Auto-generated method stub try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.callback.callBack(this.threadName); } }
test.java代碼:ide
package thread.callback; public class test { public static void main(String[] args) { for (int i=0; i<5; ++i) { ThreadCallback callback = new ThreadCallback(); WorkThread workThread = new WorkThread(callback, "thread" + Integer.toString(i)); workThread.start(); } System.out.println("to be end"); } }
代碼很是簡單啊,就是WorkThread中簡單回調Callback中的接口,而後再callback中打印一下,運行的結果以下:函數
to be end thread0 thread2 thread3 thread1 thread4
從輸出結果(thread輸出順序,每次不必定同樣)能夠看出來,主線程退出以後,其建立的幾個子線程仍是在正常運行的,直到輸出了指定的結果。那麼也就是跟以前linux C++下的主從線程關係不太同樣了。通過搜索,發現Java線程有一個是否爲守護線程的屬性,默認狀況下這個屬性是不設置的,爲false,表明這個線程是一個用戶線程,若是使用Thread的setDaemon接口設置一下,那麼線程屬性就會變成守護線程。測試
用戶線程不會隨着主線程退出而結束,而是會繼續在JVM中運行的,直到自身結束,JVM也會等全部用戶線程都執行完畢才退出。this
而守護線程會在全部用戶線程(包括主線程)退出以後,一塊兒退出,這時候JVM也就退出了。spa
咱們把test.java改爲這樣:線程
package thread.callback;
public class test {
public static void main(String[] args) {
for (int i=0; i<5; ++i) {
ThreadCallback callback = new ThreadCallback();
WorkThread workThread = new WorkThread(callback, "thread" + Integer.toString(i));
workThread.setDaemon(true);
workThread.start();
}
System.out.println("to be end");
}
}
新增setDaemon,在thread運行以前設置,而後運行程序,程序只打印"to be end"而後就退出了。code
若是咱們將5個子線程中的4個設置爲守護線程,一個爲用戶線程,會怎樣呢?
test.java代碼
package thread.callback; public class test { public static void main(String[] args) { for (int i=0; i<5; ++i) { ThreadCallback callback = new ThreadCallback(); WorkThread workThread = new WorkThread(callback, "thread" + Integer.toString(i)); if (i != 4) workThread.setDaemon(true); workThread.start(); } System.out.println("to be end"); } }
那麼也會可能輸出全部線程結果。爲啥說可能呢,這要看惟一的用戶線程thread4啥時候退出了,它一退出,那麼其餘守護進程無論有沒有執行完,都會被迫退出。在咱們上面的例子中比較難出現,由於thread4是最後一個啓動的,並且你們都作相同簡單的事情,若是把thread4改爲thread1,那麼就很是容易測試出來了。
好比咱們把WorkThread.java的run改爲這樣:
public void run() { // TODO Auto-generated method stub try { if (threadName.equals("thread4")) Thread.sleep(1000); else Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.callback.callBack(this.threadName); }
那麼輸出結果就是:
to be end thread4
能夠從上面的運行結果中看出用戶線程和守護線程的區別了!