1. 程式人生 > >java個人學習筆記16(多執行緒+extends Thread+implements Runnable)

java個人學習筆記16(多執行緒+extends Thread+implements Runnable)

1.多執行緒

程序:正在執行的應用程式在記憶體中分配的空間

執行緒:是程序中負責程式執行的執行單元,也稱執行路徑
 一個程序中至少有一個執行緒在負責該程序的執行
多執行緒技術:解決多部分程式碼同時執行的需求,合理使用cpu資源,提高使用者體驗。(微觀上序列,並未實際上提高效率)
多執行緒的執行是根據cpu的切換完成的,具有不確定性。
jvm中的多執行緒(至少2個):一個負責程式碼的執行,這個從main方法執行的執行緒稱為主執行緒。

 一個負責垃圾回收(不定時)

每一個執行緒都有執行程式碼的內容,稱之為執行緒的任務。執行緒的任務都封裝在特定的區域中。

主執行緒執行的任務都定義在main方法中

垃圾回收執行緒(finalize)在收垃圾時會執行finalize()方法。

class Demo{
	public void finalize(){//垃圾回收方法,即釋放資源。不保證該函式一定會被呼叫
		System.out.println("demo recycle");
	}
}
class FinalizeDemo{
	public static void main(String[] args) 
	{
		new Demo();
		new Demo();
		new Demo();
		new Demo();
		System.gc();//啟動垃圾回收器,不一定呼叫finalize(),由cpu切換造成的不確定性
		System.out.println("Hello World!");
	}
}

2.建立多執行緒的兩種方法

1)繼承Thread類
繼承Thread
覆蓋run()
建立子類物件就是建立執行緒物件
呼叫Thread類中的start(),同時會呼叫run()
注意:start()開啟執行緒後,都會呼叫run(),所以run()中儲存的都是執行緒要執行的程式碼。
呼叫run()和呼叫start()的區別:
呼叫start()會開啟執行緒,並用開啟的執行緒去執行run()方法中的內容
呼叫run()不會開啟執行緒,執行run()方法中內容的是main執行緒

class Demo extends Thread
{
	private String name;
	Demo(String name){
		this.name = name;
	}
	public void show(){
		for(int i = 1;i <= 10;i++)
			System.out.println(Thread.currentThread().getName()+"...."+name+"........"+i);
	}
	//Thread.currentThread()獲取當前執行執行緒的引用
	//getName()獲取執行緒的名字
	public void run(){
		show();
	}//覆蓋run()
}
class ThreadDemo
{
	public static void main(String[] args) 
	{
		Demo d1 = new Demo("Jack");
		Demo d2 = new Demo("Tom");
		d1.start();
		d2.start();
		for(int i = 1;i <= 10;i++)
			System.out.println(Thread.currentThread().getName()+"----"+"MainThread"+"......"+i);
	}
}


2)實現Runnable介面

1)定義一個類實現Runnable
2)覆蓋Runnable介面中的run方法,將執行緒要執行的任務程式碼儲存到該方法中
3)通過Thread類建立執行緒物件,並將實現了Runnable介面的物件作為Thread類的建構函式的引數進行傳遞
4)呼叫Thread類的start方法,開啟執行緒
注意:此方法將執行緒物件和執行緒任務分開了

實現Runnable介面的好處:
1)避免了繼承Thread類的單繼承的侷限性
2)Runnable介面的出現更符合面向物件,將執行緒單獨進行物件的封裝
3)Runnable介面的出現,降低了執行緒物件和執行緒任務的耦合性
所以開發多用實現Runnable介面。


多執行緒的安全問題:
產生原因:
1)執行緒任務處理到共享資料
2)執行緒任務中有多條對共享資料的操作

解決思想:
互斥地訪問臨界資源
解決辦法:
同步程式碼塊(未操作共享資料的程式碼無需同步)
synchronized(object){
需要被同步的程式碼
}

同步的前提:
多執行緒在同步中必須使用同一個鎖(object)



class SaleTicket implements Runnable
{
	private int tickets = 100;
	Object obj = new Object();//synchronized(obj),相當於“鎖”
	public void run(){
		while(true){
			synchronized(obj){//同步程式碼塊
				if(tickets > 0){
					try{
						Thread.sleep(10);//執行緒停止執行10ms
					}catch(InterruptedException e){}
					System.out.println(Thread.currentThread().getName()+"...."+tickets--);
				}
			}
		}

	}
}

class TicketSystem
{
	public static void main(String[] args) 
	{
		SaleTicket t = new SaleTicket();
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		Thread t4 = new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		t4.start();

	}
}