java基礎畢向東day11-12

1.創建線程的第二種方式:實現Runable接口

步驟:

  • 定義類實現Runnable接口
  • 覆蓋Runnable接口中的run方法。    將線程要運行的代碼存放在該run方法中。
  • 通過Thread類建立線程對象。
  • 將Runnable接口的子類對象作爲實際參數傳遞給Thread類的構造函數。    爲什麼要將Runnable接口的子類對象傳遞給Thread的構造函數。    因爲,自定義的run方法所屬的對象是Runnable接口的子類對象。    所以要讓線程去指定指定對象的run方法。就必須明確該run方法所屬對象。
  • 調用Thread類的start方法開啓線程並調用Runnable接口子類的run方法

實現方式和繼承方式有什麼區別呢?

實現方式好處:避免了單繼承的侷限性。實現了Runable後還可以extends 其他類
在定義線程時,建立使用實現方式。

兩種方式區別:
繼承Thread:線程代碼存放Thread子類run方法中。
實現Runnable,線程代碼存在接口的子類的run方法。

2.同步函數都要被對象調用,因此同步函數使用的鎖是this; 靜態同步函數所用的鎖是對象所屬的類的字節碼文件對象(類名.class)。

3.死鎖:a對象拿着A鎖,b對象拿着B鎖,a對象要進要進B鎖對應的代碼中去,b對象要進A鎖對應的代碼中來,兩者相持不下

死鎖一般發生情況:同步中嵌套同步。死鎖



class Test implements Runnable
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag = flag;
	}

	public void run()
	{
		if(flag)
		{
			while(true)
			{
				synchronized(MyLock.locka)
				{
					System.out.println(Thread.currentThread().getName()+"...if locka ");
					synchronized(MyLock.lockb)
					{
						System.out.println(Thread.currentThread().getName()+"..if lockb");					
					}
				}
			}
		}
		else
		{
			while(true)
			{
				synchronized(MyLock.lockb)
				{
					System.out.println(Thread.currentThread().getName()+"..else lockb");
					synchronized(MyLock.locka)
					{
						System.out.println(Thread.currentThread().getName()+".....else locka");
					}
				}
			}
		}
	}
}


class MyLock
{
	static Object locka = new Object();
	static Object lockb = new Object();
}

class  DeadLockTest
{
	public static void main(String[] args) 
	{
		Thread t1 = new Thread(new Test(true));
		Thread t2 = new Thread(new Test(false));
		t1.start();
		t2.start();
	}
}

5.

wait();  notify();  notifyAll();都使用在同步中,因爲要對持有監視器(鎖)的線程操作。所以要使用在同步中,因爲只有同步才具有鎖。

爲什麼這些操作線程的方法要定義Object類中呢?
因爲這些方法在操作同步中線程時,都必須要標識它們所操作線程只有的鎖,只有同一個鎖上的被等待線程,可以被同一個鎖上notify喚醒。不可以對不同鎖中的線程進行喚醒。也就是說,等待和喚醒必須是同一個鎖。而鎖可以是任意對象,所以可以被任意對象調用的方法定義Object類中。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章