1. 程式人生 > >多線程(二)

多線程(二)

程序 mit 方法調用 種類 不同的 get 所有 啟動 highlight

1、JDK5以後的針對線程的鎖定操作和釋放操作

	
		A:為了更清晰表達在哪裏如何加鎖及釋放鎖
		B:Lock鎖
			lock():加鎖
			unlock():釋放鎖
		C:ReentrantLock 是 Lock 的實現類
			private Lock lock = new ReentrantLock();
			lock.lock();	//加鎖
			...				//加鎖代碼
			lock.unlock();	//釋放鎖
			

2、死鎖問題的描述和代碼體現

	
			指兩個或兩個以上的線程在執行過程中,因爭奪資源產生的一種互相等待現象(如果出現了同步嵌套,就容易
		產生死鎖問題)		

3、生產者和消費者多線程體現(線程間通信問題)

	
		A:不同種類的線程間針對同一個資源的操作
			代碼實現:
				//在外界把這個數據創建出來,通過構造方法傳遞給其它類
				Student s = new Student();
				GetThread gt = new GetThread(s);
				SetThread st = new SetThread(s);
				
		B:以學生作為資源來實現的
		
		資源類:Student
		設置數據類:SetThread(生產者)
		獲取數據類:GetThread(消費者)
		測試類:StudentDemo
		
		代碼:
			A:最基本的版本,只有一個數據。
			B:改進版本,給出了不同的數據,並加入了同步機制
			C:等待喚醒機制改進該程序,讓數據能夠實現依次的出現
				wait()
				notify()
				notifyAll() (多生產多消費)
			D:等待喚醒機制的代碼優化。把數據及操作都寫在了資源類中
			註:這些方法調用必須通過鎖對象調用,而我們剛才使用的鎖對象是任意鎖對象。
				所以,這些方法必須定義在Object類中。		

4、線程組

		
		把多個線程組合到一起。它可以對一批線程進行分類管理,Java允許程序直接對線程組進行控制。
		public final ThreadGroup getThreadGroup():返回該線程所屬的線程組
			ThreadGroup tg = mt.getThreadGroup();
		public final String getName():返回此線程組的名稱
			String name1 = tg.getName();
		註:默認情況下,所有線程都屬於同一個組
		
		ThreadGroup(String name):修改線程所在的組
			MyRunnable my = new MyRunnable();
			ThreadGroup tg2 = new ThreadGroup("newThreadGroup");
			Thread t = new Thread(tg2, my, "threadName");
			tg2.get...		

5、線程池

		
			程序啟動一個新線程成本比較高,使用線程池可以很好的提高性能,尤其是創建大量生存期很短的線程時,
		更應該考慮使用線程池。
			線程池裏的每一個線程代碼結束後,並不會死亡,而是再次回到線程池中成為空閑狀態,等待下一個對象
		來使用。
			在JDK5之前,我們必須手動實現自己的線程池,從JDK5開始,Java內置支持線程池。
		
		線程池的實現:
			A: 創建一個線程池對象,控制要創建幾個線程對象
				public static ExecutorService newFixedThreadPool(int nThreads)
			B: 這種線程池可以執行
				可以執行Runnable對象或者Callable對象代表的線程
				做一個類實現Runnable接口
			C: 調用如下方法即可
				Future<?> submit(Runnable task)
				 Future submit(Callable task)
			D: 非要結束
				pool.shutdown();
			代碼案例:
				public static void main(String[] args){
					//創建一個線程池對象,控制要創建幾個線程對象
					ExecutorService pool = new ExecutorService.newFixedThreadPool(2);
					
					//可以執行Runnable對象或者Callable對象代表的線程
					pool.submit(new MyRunnable());
					pool.submit(new MyRunnable());
					
					//結束線程池
					pool.shutdown();
				}

6、多線程實現的第三種方案

		
		實現Callable接口,與Runnable類似
		代碼案例--10

7、匿名內部類方式實現多線程

		
		A:new Thread(){代碼...}.start();
		B:new Thread(new Runnable(){代碼...}){}.start();
		代碼案例:
			//繼承Thread類來實現多線程
			new Thread(){
				public void run(){
					...
				}		
			}.start();
			
			//實現Runnable接口來實現多線程
			new Thread(new Runnable(){
				public void run(){
					...
				}
			}){}.start();

8、定時器

		
		可在指定時間執行某任務,還可以重復執行
		依賴Timer 和TimerTask
			Timer:定時
				public Timer()
				public void schedule(TimerTask task, long delay)
				public void schedule(TimerTask task)
				public void cancel();
			代碼案例:
				public static void main(String[] args){
					//創建定時器對象
					Timer t = new Timer();
					
					//3秒後執行爆炸任務
					//t.schedule(new MyTask(), 3000);
					//結束任務
					t.schedule(new MyTask(t), 3000);					
				}
				class MyTask extends TimerTask(){
					private Timer t;
					public MyTask(){}
					public MyTask(Timer t){
						this.t = t;
					}
					public void run(){
						System.out.println("beng!!!");
						t.cancel();
					}
				}

9、多線程的面試題

		
		A:多線程有幾種實現方案,分別是哪幾種?
			繼承Thred類
			實現Runnable接口
			擴展:實現Callable接口,需要和線程池結合
		B:同步有幾種方式,分別是什麽?
			兩種
			同步代碼塊
			同步方法
		C:啟動一個線程是run()還是start()?他們的區別是?
			start();
			run():封裝了被線程執行的代碼,直接調用僅僅是普通方法調用
			start():啟動線程,並由JVM自動調用run()方法
		D:sleep()和wait()方法的區別
			sleep():必須指定時間。不釋放鎖
			wait():可以不指定時間,也可以指定時間,釋放鎖。
		E:為什麽wait(),notify(),notifyAll()等方法定義在Object類中
			因為這些方法的調用是依賴鎖對象的,而同步代碼塊的鎖對象是任意鎖。
		F:線程的生命周期
			新建--就緒--運行--死亡
			新建--就緒--運行--阻塞--就緒--運行--死亡
			建議畫圖解釋

多線程(二)