最近工做上有個地方須要用到多線程,是用C++的,下午加班改代碼,可是網絡出現問題,連不了主機,因而在java上面測試並回顧了一些知識。記錄一下。java
1.多線程的類helloworld。網絡
在thread類中持有一個實現了runnable接口的實例化對象,而後thread類run的時候,會調用runnable的run。這一點在不少入門的書籍中都有介紹,不必贅述,可是爲何要這麼寫,這裏稍微把java中的代碼粘貼一下。代碼以下:多線程
Thread類有一個接受runnable實現對象的構造函數,ide
public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }
init函數中最重要的一段代碼是:this.target = target;函數
即給Thread的target這個變量set成了傳進來的target。當Thread的run執行的時候,實際上會調用target的run函數。在源碼中是這麼說的「/**
* Causes this thread to begin execution; the Java Virtual Machine
* calls the <code>run</code> method of this thread.」oop
也就是Thread的start執行之後調用Thread的run方法。而run方法會調用target的run方法,代碼以下:測試
public void run() { if (target != null) { target.run(); } }
測試的Thread主類以下:this
public class TestThread { static int threadNum = 10; static int maxloop = 10000; public static void main(String arg[]) { Thread threads[] = new Thread[100]; for( int i = 0; i <= threadNum ; ++i) { String threadName = "Thread " + Integer.valueOf(i); threads[i] = new Thread(new TestRunable(threadName,maxloop)); threads[i].start(); } for( int i = 0; i <= threadNum ; ++i) { try { threads[i].join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Integer.valueOf(i) + "thread done."); } System.out.println( "count==" + Integer.valueOf( Global.count ) ); } }
這裏用到了一個全局變量Global.count,其目的在下面第三點說明。線程
2.測試join函數。join函數就是等待自身的函數,其效果以下:code
8thread done.
。。。
Thread 9 9999
Thread 9 10000
9thread done.
10thread done.
也就是在線程8結束之後,線程9還未結束,那麼主線程就一直等待線程9結束之後,再等待線程10結束,而後再繼續往下執行。
3.測試線程操做統一個未上鎖的變量的狀況。
這裏先把實現了runnable接口的類也貼出來。
package test; public class TestRunable implements Runnable { private int mi; String ms; int mmaxloop; @Override public void run() { // TODO Auto-generated method stub for( int i = 0;i<=mmaxloop*10;++i ) { System.out.println( ms + " " + Integer.valueOf(mi)); ++mi; ++Global.count; } } TestRunable(String ss,int maxLoop) { this.mi = 0; this.ms = ss; mmaxloop = maxLoop; } }
此外,還有全局變量的類也一道貼出來:
public class Global { public static int count = 0; }
其結果是每次測試的結果,對全局變量的打印數字都不一致。
好比,某次執行的結果是(對源碼中的某些數字可能進行一些放大或者縮小,不影響其效果):
7thread done.
8thread done.
9thread done.
10thread done.
count==1100010
另一次執行的結果是:
7thread done.
8thread done.
9thread done.
10thread done.
count==1100011
4.互斥實現。
testRunnable類的代碼修改成:
for( int i = 0;i<=mmaxloop*100;++i ) { System.out.println( ms + " " + Integer.valueOf(mi)); ++mi; synchronized(this) { ++Global.count; } }
再執行屢次,查看Global.count結果,都是一個值嗎?
第一次:
count==1100009
第二次:
8thread done.
9thread done.
10thread done.
count==1100011
因而,發現根本就沒有完成互斥。
5.原來互斥是須要針對一個對象的。通過修改之後的代碼以下,就能夠完成互斥了。
static int threadNum = 10; static int maxloop = 1000; public static void main(String arg[]) { Thread threads[] = new Thread[100]; System.out.println("ssssssssssss"); Global global = new Global(); String threadName = "same"; TestRunnable testRunnable = new TestRunnable(threadName, maxloop, global); for (int i = 0; i <= threadNum; ++i) { // String threadName = "Thread " + Integer.valueOf(i); threads[i] = new Thread(testRunnable); threads[i].start(); } for (int i = 0; i <= threadNum; ++i) { try { threads[i].join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // System.out.println(Integer.valueOf(i) + "thread done. mi==" + // Integer.valueOf(threads[i].g)); System.out.println(Integer.valueOf(i) + "thread done. global.count==" + Integer.valueOf(global.count)); } System.out.println("count==" + Integer.valueOf(global.count)); }
results:
count==1100000
執行屢次都是一個結果。