1. 程式人生 > >Java執行緒與執行緒安全,開啟多執行緒及每執行緒迴圈10次對類進行輸出測試

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寫成全域性變數,會有執行緒安全問題。加個鎖就安全啦,鎖就像麥田裡的守望者,拉住每個跑向懸崖的孩子,因為他們跑起來不看路

寫到這先,有錯或有問題望指出~