Java執行緒與執行緒安全,開啟多執行緒及每執行緒迴圈10次對類進行輸出測試
最近看到執行緒問題,emmm~腦闊回想到計算機作業系統貌似又講,不過上課睡覺覺去啦哈哈哈,java課老師莫得講~
然歸正傳,今對執行緒進行查閱及測試,做一下筆記,有錯之處還請指出,謝謝~上程式碼之前呢先說一哈前傳
執行緒是程序中的最小執行單位:
手機呢會有很多單獨執行的程式,每個程式有一個獨立的程序,而程序之間是相互獨立存在的,所以手機開很多應用也問題不大就是這個原因。一個程序中至少有一個執行緒。例如常用的微信,一遍放著朋友圈的歌曲,一條刷圈或髮圈,就至少兩個執行緒並行了。
多執行緒又分為序列和並行:
先說並行:例如迅雷,可以同時進行多個任務下載
package thread; public class ThreadTest { public void name() { for (int a = 0;a < 10; a++) { System.out.println(Thread.currentThread().getName() + " " + a); } } public static void main(String[] args) { ThreadTest test = new ThreadTest(); Thread t1 = new Thread(new Runnable() { @Override public void run() { test.name(); } }, "t1"); // 建立一個新的執行緒 t1 此執行緒進入新建狀態 Thread t2 = new Thread(new Runnable() { @Override public void run() { test.name(); } }, "t2"); // 建立一個新的執行緒 t1 此執行緒進入新建狀態 t1.start(); // 呼叫start()方法使得執行緒進入就緒狀態 t2.start(); // 呼叫start()方法使得執行緒進入就緒狀態 } }
執行結果
從程式執行的結果可以發現,多執行緒程式是亂序執行。
當呼叫執行緒物件的start()方法(t.start();),執行緒即進入就緒狀態。處於就緒狀態的執行緒,只是說明此執行緒已經做好了準備,隨時等待CPU排程執行,並不是說執行了t.start()此執行緒立即就會執行;
序列:與並行相反,一次只能下載一個 ,下載完了才能下載下一個。改一下程式碼,防止異常,講lock.unlock放在finally裡面,因為finnally一定會被執行
final Lock lock = new ReentrantLock(); ThreadTest test = new ThreadTest(); Thread t1 = new Thread(new Runnable() { @Override public void run() { lock.lock(); //獲得鎖 try { test.name(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); //釋放鎖 }
執行結果顯而易見,不多解釋了
好了,接下來是多執行緒安全問題
執行緒安全:
程式碼所在的程序中有多個執行緒訪問,若每次執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,則執行緒是安全的。
package thread; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class abc { private static int a,b,c = 0; Integer count = 0; public void getCount() { count++; System.out.println(count); } private void methode(Thread thread) { //lock.lock(); try { System.out.println("執行緒名: " + thread.getName() + "獲得了鎖"); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { System.out.println("執行緒名: " + thread.getName() + "釋放了鎖"); // lock.unlock(); } } public static void main(String[] args) { final Lock lock = new ReentrantLock(); abc count = new abc(); Thread A = new Thread(new Runnable() { @Override public void run() { while (a < 10) { //lock.lock(); // 獲取鎖物件 try { count.getCount(); a++; // Thread.currentThread() 返回當前執行緒的引用 count.methode(Thread.currentThread()); } catch (Exception e) { e.printStackTrace(); } finally { //lock.unlock(); } } } }, "A"); Thread B = new Thread(new Runnable() { @Override public void run() { while (b < 10) { //lock.lock(); try { count.getCount(); b++; count.methode(Thread.currentThread()); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { // lock.unlock(); } } } }, "B"); Thread C = new Thread(new Runnable() { @Override public void run() { while (c < 10) { //lock.lock(); try { count.getCount(); c++; count.methode(Thread.currentThread()); } catch (Exception e) { e.printStackTrace(); } finally { //lock.unlock(); } } } }, "C"); A.start(); B.start(); C.start(); } }
跑一下
出現了兩個數字2,count++還未未完成修改就被另一程序使用,導致出現2個2
因此需要Lock或者synchronized來確保執行緒安全,此處先講Lock方法,
將上文程式碼裡的lock.lock和lock.unlock註釋去掉,則執行結果為:
前文講過:多執行緒是亂序執行的,看誰跑得快咯
程式碼開頭將count=0寫成全域性變數,會有執行緒安全問題。加個鎖就安全啦,鎖就像麥田裡的守望者,拉住每個跑向懸崖的孩子,因為他們跑起來不看路
寫到這先,有錯或有問題望指出~