天天看點

黑馬程式員_多線程(下)多線程(下)

------- android教育訓練、java教育訓練、期待與您交流! ----------

多線程(下)

第四節:線程的排程

★線程的排程有兩種模型

  • 分時排程模型:指讓所有的線程輪流活的CPU的使用權。
  • 搶占式排程模型:指随機擷取CPU的使用權,這個是Java虛拟機預設采用的模型。

★線程的優先級

  • 在應用程式中,可以直接設定線程的優先級。優先級越高的線程獲得CPU執行的機會就越大。

★線程休眠

  • 靜态方法sleep(long millis)可以讓目前正在執行的線程暫停一段時間,進入休眠狀态。
  • 目前線程調用sleep(long millis)方法後,在指定時間(參數millis)内是不會執行的。
  • sleep(long millis)方法聲明抛出InterruptedException異常。
  • 是以在調用sleep(long millis)方法時應該聲明抛出該異常或者捕獲異常。

★線程讓步

  • 線程讓步可以通過yield()方法實作,跟sleep()相似,都可以讓正在運作的線程暫停
  • 差別在yield()方法不會阻塞該線程,它隻是将線程轉換成就緒狀态,讓系統的排程器重新排程。

★線程插隊

  • 線程插隊用join()方法,當在某個線程中調用其他線程的join()方法時,調用的線程将被阻塞,
  • 知道被join()方法加入的線程執行完成後它才會繼續運作。

第五節:線程的安全與同步

★線程安全問題其實就是由多個線程同時處理共享資源所導緻的。

★解決問題思路:必須的保證用于處理共享資源的代碼紮起任何時刻隻能有一個線程通路。

  • 代碼執行原理:synchronized(lock){操作共享資源代碼塊}
  • 上面的代碼中,lock是一個鎖對象,它是同步代碼塊的關鍵。
  • 當線程執行到同步代碼塊時,首先會檢查鎖對象的标志位
  • 預設情況下标志位為1,此時線程會執行同步代碼塊,
  • 同時将鎖對象的标志位置變為0。
  • 當一個新的線程執行到這段同步代碼塊的時候,
  • 由于鎖對象的辨別為0,新線程發生阻塞,等待目前線程執行完同步代碼塊後,
  • 鎖對象的标志位變為1,新線程才能進入同步代碼塊執行其中的代碼。
  • 如此循環往複。直到共享資源被處理完為止。
package cn.itbasis;
/*
 * 售票系統
 */
public class Example03 {
	public static void main(String[] args) {
		//建立Ticket1對象
		Ticket1 ticket = new Ticket1();
		//建立new Thread()——并開啟.start——4個線程
		new Thread(ticket,"線程1").start();
		new Thread(ticket,"線程2").start();
		new Thread(ticket,"線程3").start();
		new Thread(ticket,"線程4").start();
		
	}
}
//定義一個Ticket1類實作Runnable接口
class Ticket1 implements Runnable{
	//定義Ticket1并指派10共享資源
	private int tickets = 10;
	//定義一個對象用于同步代碼塊的鎖
	Object lock = new Object();
	public void run(){
		while(true){
			//定義同步代碼塊
			synchronized(lock){
				//sleep()要抛異常,設定睡眠為10毫秒
				try{
				Thread.sleep(10);
				}catch(InterruptedException e){
					e.printStackTrace();
				}
				if(tickets>0){
					//如果ticket1小于0,跳出循環
					System.out.println(Thread.currentThread().getName()+"---賣票"+tickets--);
				}else{
					break;
				}
			}
		}
	}
	
}
           
  • 同步方法:synchronization傳回值類型 方法名([參數1,......]){}
  • 死鎖問題:兩個程式都在等待對方的鎖,這樣就造成了程式的停滞,稱為死鎖。

第六節:多線程通信

★可以了解一種合作機制,兩個線程之間協同完成工作

  • 不恰當的例子:用水管澆花,管子一頭進水,一頭出水澆花,
  • 整個水管就是一個容器,進水口跟出水口就是2個線程

★喚醒線程的方法:Object類的三個方法,任何類的對象都可以直接使用的三個方法

  • void wait():使目前線程放棄同步鎖進入等待,直到其他線程進入同步鎖,
  • 其他線程進入同步鎖後調用notify()或notifyAll()方法喚醒該線程為止
  • void notify():喚醒此同步鎖上等待的第一個調用wait()方法的線程
  • void notifyAll():喚醒此同步鎖上調用wait()方法的所有線程

繼續閱讀