1. 程式人生 > >多執行緒學習(二):執行緒間的資料共享

多執行緒學習(二):執行緒間的資料共享

資料不共享的情況

public class MyThread04 extends Thread{
	private int count=5;
	public MyThread04(String threadName) {
		this.setName(threadName);
	}
	
	@Override
	public void run() {
		while(count>0){
			count--;
			System.out.println(Thread.currentThread().getName()+"-----"+count);
		}
	}
	public static void main(String[] args) {
		new MyThread04("第一個執行緒").start();
		new MyThread04("第二個執行緒").start();
		new MyThread04("第三個執行緒").start();
	}
}

執行結果

在這裡插入圖片描述
上述建立了3個物件,這3個物件的資料是互相不共享的。

資料共享的情況

public class MyThread05 extends Thread{
	private int count=5;
	@Override
	public void run() {
		count--;
		System.out.println(Thread.currentThread().getName()+"-----"+count);
	}
	public static void main(String[] args) {
		MyThread05 myThread05=new MyThread05();
		new Thread(myThread05,"第一個執行緒").start();
		new Thread(myThread05,"第二個執行緒").start();
		new Thread(myThread05,"第三個執行緒").start();
		new Thread(myThread05,"第四個執行緒").start();
		new Thread(myThread05,"第五個執行緒").start();
	}
}

執行結果

在這裡插入圖片描述
上述執行的5個執行緒,使用的資料都是一個物件的資料,即count變數是共享的,所以出現了“非執行緒安全”的問題(非執行緒安全指多個執行緒對同一個物件中的同一個例項變數進行操作時會出現值被更改、值不同步的情況,進而影響程式的執行流程)。
出現count一樣的情況,可以使用synchronized關鍵字來避免。
在這裡插入圖片描述

執行結果

在這裡插入圖片描述
synchronized修飾的方法或程式碼塊,這段加鎖的程式碼稱為“互斥區”或“臨界區”。

i–與System.out.println()的異常

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

currentThread()方法

currentThread()方法是一個static方法,它可以返回當前程式碼正在被哪個執行緒呼叫的資訊。

public class MyThread01 extends Thread{
	@Override
	public void run() {
		System.out.println("子執行緒名:"+Thread.currentThread().getName());
	}

	public static void main(String[] args) {
		new MyThread01().start();  //呼叫子執行緒
		System.out.println("主執行緒名:"+Thread.currentThread().getName());
		new MyThread01().run();    //這樣呼叫run只是普通方法,是主執行緒呼叫
	}
}

在這裡插入圖片描述
在這裡插入圖片描述

稍微複雜一點的例子

public class MyThread07 extends Thread{
	public MyThread07() {
		System.out.println("構造方法:"+Thread.currentThread().getName());
		System.out.println("構造方法:"+this.getName());
	}
	@Override
	public void run() {
		System.out.println("run:"+Thread.currentThread().getName());
		System.out.println("run:"+this.getName());
	}

	public static void main(String[] args) {
		MyThread07 myThread07 = new MyThread07();
		Thread thread=new Thread(myThread07);
		thread.setName("AAA");
		thread.start();
	}
}

在這裡插入圖片描述
結果分析:
首先,Thread.currentThread().getName()表示的是當前執行緒被誰呼叫,MyThread07物件是主執行緒建立的,所以是由主執行緒呼叫,結果是"main"。
run方法是由thread呼叫,thread的name是"AAA",所以Thread.currentThread().getName()列印的是"AAA",
兩處this.getName是myThread07物件的name,預設是Thread-0。