多線程編程簡單例子學習(1)

一道線程題目引出的問題:
    1. 題目: 設計4個線程,其中兩個線程每次對j增長1,另外兩個線程對j每次減小1。寫出程序。
    2. 實現:
       資源類:
package com.lxh.Thread2;
// 資源類
public class Resource {
	// 初始值
	public int initValue = 0;
}
       加1線程類:
package com.lxh.Thread2;
// 加1操做
public class IncreaseThread implements Runnable {
	// 變量
	public Resource res;
	// 構造方法
	public IncreaseThread(Resource resource) {
		this.res = resource;
	}
	@Override
	public void run() {
		for(int i=0;i<5;i++){
			synchronized (res) {
				this.res.initValue = res.initValue + 1;
				System.out.println(res+"***當前線程" + Thread.currentThread().getName()
						+ ",加1以後initValue=" + res.initValue + "***");
			}
		}
	}
}
       減1線程類:
package com.lxh.Thread2;
// 減1操做
public class ReduceThread implements Runnable {
	// 變量
	public Resource res;
	// 構造方法
	public ReduceThread(Resource resource) {
		this.res = resource;
	}
	@Override
	public void run() {
		for(int i=0;i<5;i++){
			synchronized (res) {
				this.res.initValue = res.initValue - 1;
				System.out.println(res+"***當前線程" + Thread.currentThread().getName()
						+ ",減1以後initValue=" + res.initValue + "***");
			}
		}
	}
}
       測試類:
package com.lxh.Thread2;

public class Test {
	public static void main(String[] args) {
		Resource res = new Resource();
		
		IncreaseThread it = new IncreaseThread(res);
		ReduceThread rt = new ReduceThread(res);
		
		Thread t1 = new Thread(it);
		Thread t2 = new Thread(it);
		Thread t3 = new Thread(rt);
		Thread t4 = new Thread(rt);
				
		t1.start();
		t2.start();
		t3.start();
		t4.start();		
	}
}
    3. 運行結果       

     小結: 這是一個簡單的"生產者----消費者"應用。  (爲何定一個資源類做爲參數傳遞? 由於這樣的話能夠保證initValue值在4個線程中共享,若是隻是定義一個int類型的變量則只能在相同的線程之間共享,好比同增或同減,不能在不一樣線程之間共享,好比加1線程和減1線程之間進行共享。) java

    4. 若是在測試類中設置線程優先級,相關程序以下: 安全

package com.lxh.Thread2;
// 加1操做
public class IncreaseThread implements Runnable {
	// 變量
	public Resource res;
	// 構造方法
	public IncreaseThread(Resource resource) {
		this.res = resource;
	}
	@Override
	public void run() {
		for(int i=0;i<20;i++){
			synchronized (res) {
				this.res.initValue = res.initValue + 1;
				System.out.println(res+"***當前線程" + Thread.currentThread().getName()
						+ ",加1以後initValue=" + res.initValue + "***");
			}
		}
	}
}

package com.lxh.Thread2;

// 減1操做
public class ReduceThread implements Runnable {
	// 變量
	public Resource res;
	// 構造方法
	public ReduceThread(Resource resource) {
		this.res = resource;
	}
	@Override
	public void run() {
		for(int i=0;i<15;i++){
			synchronized (res) {
				this.res.initValue = res.initValue - 1;
				System.out.println(res+"***當前線程" + Thread.currentThread().getName()
						+ ",減1以後initValue=" + res.initValue + "***");
			}
		}
	}
}

package com.lxh.Thread2;

public class Test {
	public static void main(String[] args) {
		Resource res = new Resource();
		
		IncreaseThread it = new IncreaseThread(res);
		ReduceThread rt = new ReduceThread(res);
		
		Thread t1 = new Thread(it);
		Thread t2 = new Thread(it);
		Thread t3 = new Thread(rt);
		Thread t4 = new Thread(rt);
		
                // 設置線程優先級
		t1.setPriority(Thread.MIN_PRIORITY);// 優先級最低
		t2.setPriority(Thread.MAX_PRIORITY);// 優先級最高
		t3.setPriority(3);
		t4.setPriority(7);
		
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		
	}
}
          運行結果:

     小結:線程的優先級是能夠調節的,最高級爲10(Thread.MAX_PRIORITY),最低級爲1(Thread.MIN_PRIORITY),默認爲Thread.NORM_PRIORITY,越大得到CPU資源的能力就越強,特別說明:線程執行的次數多的時候該規律才明顯。  多線程

      5. 爲何須要加synchronized關鍵字?代碼說明 ide

package com.lxh.Thread2;

// 減1操做
public class ReduceThread implements Runnable {
	// 變量
	public Resource res;
	// 構造方法
	public ReduceThread(Resource resource) {
		this.res = resource;
	}
	@Override
	public void run() {
                System.out.println(res.initValue); 
                for(int i=0;i<15;i++){
				this.res.initValue = res.initValue - 1;
				System.out.println(res+"***當前線程" + Thread.currentThread().getName()
						+ ",減1以後initValue=" + res.initValue + "***");
		}
	}
}
package com.lxh.Thread2;

public class Test {
	public static void main(String[] args) {
		Resource res = new Resource();
		
		IncreaseThread it = new IncreaseThread(res);
		ReduceThread rt = new ReduceThread(res);
		
		Thread t3 = new Thread(rt);
		Thread t4 = new Thread(rt);
				
		t3.start();
		t4.start();		
	}
}
運行結果:

       產生錯誤緣由
           Thread-3線程先獲取CPU資源執行,輸出res.initValue值(初始爲0),剛執行到for循環裏面,線程Thread-2就奪取了CPU資源,此時Thread-3在(this.res.initValue=res.initValue-1)到處於閒置狀態(不能說是等待狀態wait---等待狀態須要喚醒notify),而後Thread-2就開始輸出res.initValue值,而後,進入for循環,執行this.res.initValue = res.initValue-1;此時res.initValue=-1,就在此刻,Thread-3從新奪回CPU資源,執行this.res.initValue=res.initValue-1;此時res.initValue=-2,輸出1這行代碼,這個時候,Thread-2又從新奪回CPU資源,執行2這行代碼。
           這就很好揭示了多線程出現安全問題的緣由:多個線程在同時執行某多行代碼的時候,一個線程只執行了多行代碼的部分,其餘線程就參與進來執行,形成共享數據錯誤。解決方案就是:在共享代碼段加上synchronized關鍵字。 測試

相關文章
相關標籤/搜索