java多線程編程(黑馬程序員)

------- android培訓、java培訓、期待與您交流! ----------

多線程技術可以說是java中很重要的一個環節!

那麼如何創建一個線程一般有兩種方式:

1.繼承Thread類,複寫run方法

/*這是第一種方法開啓一個線程:去繼承Thread類
 * 需要複寫run方法
 * */
class threadFristDemo extends Thread
{
	public void run()
	{
		for(int i=0;i<10;i++)
		{
			System.out.println("this is frist"+i);
		}
	}
}

2.繼承Runnable接口,複寫run方法

/*這是第二種方法開啓一個線程:去繼承Runnable接口
 *需要複寫run方法
 * */
class threadSecondDemo implements Runnable
{
	public void run()
	{
		for(int i=0;i<10;i++)
		{
			System.out.println("this is second"+i);
		}
	}
}
那麼如何開啓線程呢?

//這裏也說一下一般開發都是繼承Runnable接口!因爲這樣的擴展性強。你可以讓你的類去做你想做的事!
	//比如在繼承其他的類和接口!
	/*這裏是開啓兩個線程的實例,無論什麼方法都必須去用start()開啓! 
	 * */
	public static void threadDemo_0()
	{
		new threadFristDemo().start();
		new Thread(new threadSecondDemo()).start();
	}

一般都是調用都是start()方法區開啓!千萬不要調用run就好比是函數調用!

2.多線程編程

主要的解決因素爲資源共享問題:1.可以用同步代碼塊

/*
 * 該方法解決時用了同步代碼塊
class saleDemo implements Runnable
{
	private static int ticket=100;
	public void run() {
		while(ticket>0)
		{	
		show();
		}

	}
	public synchronized void show()
	{
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread()+"----"+ticket--);	
	}
}
*/

2.可以用同步函數來解決:

class saleDemo implements Runnable
{
	private static int ticket=100;
	Object obj = new Object();
	public void run() {		
		while(ticket>0)
		{
			synchronized(obj)//注意這裏能否用new Object()?不能,。這樣會創建多個匿名Object
			{
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread()+"----"+ticket--);
			}
		}
	}
}

那麼主函數可與這樣寫:

public static void threadDemo_1()
	{
		new Thread(new saleDemo()).start();//這裏啓動了3個線程
		new Thread(new saleDemo()).start();
		new Thread(new saleDemo()).start();
		System.out.println(Thread.activeCount());//獲取當前活動線程數!這裏顯示是4,也就是說還有一個主線程。
		System.out.println(Thread.currentThread());//獲取當前線程的信息
		System.out.println(Thread.currentThread().getName());//獲取當前線程名稱
	}	



這裏主要是由於線程的 資源共享問題的解決!
本例子雖然是創建了不同的對象,但是ticket爲static的,所以內存中只有一份!也可作爲demo
但是有一點不能驗證synchronized函數方法!原因?你懂得!
解決資源共享問題的方法有1.synchronized(new Object()){}代碼塊2.synchronized函數
要注意他們的鎖的不同!
3
.死鎖問題:該死鎖程序的主要前提是有兩個鎖!訪問統一資源!當你的鎖嵌套時會出現相互鎖的情況! 我們在開發的時候要避免死鎖!

public static void threadDemo_2()
	{
		deadLock dl = new deadLock();
		new Thread(dl).start();
		try {
			Thread.sleep(100);//加不加這一句是出現死鎖的關鍵!
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		new Thread(dl).start();
	}

class deadLock implements Runnable
{
	private int ticket = 1000;
	private boolean flag = true;
	Object o1 =new Object();
	Object o2 =new Object();
	public void run()
	{
		show();
	}	
	public void show()
	{
		if(flag)
		{
			flag = false;
			synchronized(o1)
			{
				System.out.println("t-o1");
				synchronized(o2)
				{
					System.out.println("t-o1-02");
					System.out.println(ticket--);
				}
			}
		}
		else
		{
			synchronized(o2)
			{
				System.out.println("f-02");
				synchronized(o1)
				{
					System.out.println("f-02-01");
					System.out.println(+ticket--);
				}	
			}
		}
		
	}
}

這樣就會產生死鎖,我們分析一下原因是:由於鎖嵌套鎖導致的,也就是說當有一個資源同時被兩個鎖給鎖住了!

4.我們來看一個線程間通訊的例子,主要解決的問題是線程交替運行:

/*在生產和消費的問題中,最核心的就是數據共享和數據的交替使用!
 * 數據共享可以用synchronized方法解決!
 * 數據交換使用,可以用wait和notify來使用使得線程停止和解凍!
 * 合理的使用函數就可以讓數據交替合理的出現和使用
 * */
class res //定義一個資源
{
	private String sal = null;//商品名稱
	public static int count = 0; //商品編號
	public boolean flag = false;//標誌位
	//jdk1.5之後產生了Lock方法,有ReentrantLock產生一個對象!便可以用lock和unlock加減鎖
	//而且可以有Condition對象,condition對象有await和singleAll方法
	//使用十分方便!可以有單獨解鎖生產線程或消費線程的方法!
	private Lock mylock;
	private Condition cond_pro;
	private Condition cond_con;
	res()
	{
		this.mylock = new ReentrantLock();
		this.cond_pro = mylock.newCondition();
		this.cond_con = mylock.newCondition();
		
	}
	public void setSal(String sal)
	{
		this.sal =sal+count;
	}
	public String getSal()
	{
		return sal;
	}
	public void jdk5_pro()//jdk5.0之後的新方法
	{
		mylock.lock();
		while(flag)
			try {
				cond_pro.await();//該方法的解凍必須由cond_pro.singleAll()來
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		
		count++;
		setSal("mango");
		System.out.println("pro----------"+getSal());
		flag = true;
		
		cond_con.signalAll();//只能解凍cond_con。await()的線程
		mylock.unlock();
	}
	public void jdk5_con()
	{
		mylock.lock();
		while(!flag)
			try {
				cond_con.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		System.out.println("con_eat:"+getSal());
		flag = false;
		
		cond_pro.signalAll();
		mylock.unlock();
	}
	public synchronized void pro_sal()//生產方法
	{	
		while(flag)//如果是1	個生產者就可以用if來判斷	
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			count++;
			setSal("mango");
			System.out.println("pro----------"+getSal());
			
			flag = true;
			this.notifyAll();//喚醒線程池中的全部等待線程
	}
	public synchronized void con_sal()//消費方法
	{
		while(!flag)//如果是1個消費者者就可以用if來判斷	
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("con_eat:"+getSal());
		 
		 	flag = false;
		 	this.notifyAll();
	}
}
//生產者類
class pro implements Runnable
{
	private res r;//做一個共享資源!
	pro(res r)
	{
		this.r = r;
	}
	@Override
	public void run() 
	{
		while(r.count<100)
			r.jdk5_pro();
	}
}
//消費者類
class consumer implements Runnable
{
	private res r;
	consumer(res r)
	{
		this.r = r;
	}
	@Override
	public void run() 
	{
		while(r.count<100)
		{
		r.jdk5_con();
		}
	}

}

這些代碼中有兩種產生方式:1.jdk1.5之前我們用wait和notify。2jdk1.5之後的Lock和Condition方式。

public static void main(String[] args) {
		res r = new res();
		pro p =new pro(r);
		consumer c =new consumer(r);
		new Thread(p).start();//注意的是兩個線程通信和多個線程通訊時不同的
		new Thread(p).start();
		new Thread(c).start();
		new Thread(c).start();
	}

這是主函數的開啓。代碼中我們可以看出Lock鎖更加方便,而且Condition對象可以分別解凍結狀態!

注意幾個線程函數:

1.interrupted()方法是把那些凍結狀態的線程解凍!併產生一個異常
2.setDaemon()是把該線程設爲守護線程,在沒有其他線程存在時jvm不會管守護線程。
 該方法必須在調用start之前!
3.join()是爲了讓別的等待他終止!如t1.join時候,必須等t1調用完事之後再執行其他!
4.yield()釋放執行權

------- android培訓、java培訓、期待與您交流! ----------

發佈了27 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章