JAVA基礎之線程

進程:正在進行中的程序(直譯)。


線程:就是進程中一個負責程序執行的控制單元(執行路徑)。
一個進程中可以有多個執行路徑,稱之爲多線程。


一個進程中至少要有一個線程。
開啓多個線程是爲了同時運行多部分代碼。
每一個線程都有自己運行的內容,這個內容可以稱爲線程要執行的任務。


創建線程方式一:
繼承Thread類。


步驟:
1.定義一個類繼承Thread類。
2.覆蓋Thread類中的run方法。
3.直接創建Thread的子類對象創建線程。
4.調用start方法開啓線程並調用線程的任務run方法執行。

比如

class XianCheng extends Thread
{
	private String name;
	XianCheng(String name)
	{
		this.name=name;
	}
	public void run()
	{
		for (int a=0;a<10 ;a++ )
		{
			//for (int b=-9999999;b<999999999 ;b++ )	{}
		
			System.out.println(name+"....."+a+Thread.currentThread().getName());
			
		}
	}
}
創建線程方式二:實現Runnable接口。

步驟:
1.定義類實現Runnable接口。
2.覆蓋接口的run方法,將線程的任務代碼封裝到run方法中。
3.通過Thread類創建線程對象,並將Runnable接口的子類對象作爲Thread類的構造函數的參數進行傳遞。
因爲線程的任務都封裝在Runnable接口子類對象的run方法中。
所以要在線程對象創建時就必須明確要運行的任務。
4.調用線程對象的start的方法開啓線程。


實現Runnable接口的好處:
1.將線程的任務從線程的子類中分離出來,進行了單獨的封裝。
按照面向對象的思想將任務代碼封裝成對象。
2.避免了Java單繼承的侷限性。


所以,創建線程第二種方式比較常用。


比如:

class Fu
{
	int NUM=9;
	String name="凌晗";
}	
class Zi extends Fu implements Runnable
{
	private String name;
	Zi(String name)
	{
		this.name=name;
	}
	public void run()
	{
		show();
	}
	public void show()
	{
		for (int a=1;a<=20 ;a++ )
		{
			System.out.println(name+"...."+a+Thread.currentThread().getName());
			
		}
	}
}
創建線程應用練習


春運(現在是2016年的春節,好應景- - 從成都到遂寧這麼近我的票都不好買)有200張票,分四個窗口賣。




線程安全問題產生的原因:
1.多個線程在操作共享的數據。
2.操作共享數據的線程代碼有多條。

當一個線程在執行操作共享數據的多條代碼過程中,其他線程參與了運算,
就會導致線程安全問題的產生。


線程安全問題的解決方法:


就是將多條操作共享數據的線程代碼封裝起來,當有線程在執行這些代碼的時候
其他線程不可以參與運算。
必須要當前線程把這些代碼執行完畢後,其他線程纔可以參與運算。

在Java中,同步代碼塊能解決這個問題。
同步代碼塊的格式:
synchronized(對象)
{
需要被同步的代碼塊;
}


同步代碼塊的好處與弊端:
好處:解決了線程的安全問題。
弊端:相對降低了效率,因爲同步外的線程都會判斷同步鎖。

同步的前提:同步中必須有多個線程並使用同一把鎖。
class Piao implements Runnable
{
	private int NUM=200;
	Object obj=new Object();
	public void run()
	{
		sale();
	}
	public void sale()
	{
		while (true)
		{
			synchronized (obj)
			{
				if (NUM>0)
				{
					System.out.println(NUM--+"......回家....."+Thread.currentThread().getName());
				}
			}
		}
	}
}
同步練習,順便引申出同步函數的概念。
同步函數:即普通函數加上同步同步關鍵字,就能有同步的特性。


練習:兩個儲戶到銀行裏去存錢,每人每次存100,每人存三次。


比如:

class Bank
{
	private int sum;
	private Object obj=new Object();//同步函數後,這條語句可省略不寫。
	/*public void add(int num)
	{
		synchronized (obj)
		{
			sum=sum+num;
			System.out.println("sum="+sum);
		}
	}
	同步函數的語法就是將add方法加上同步關鍵字使其具有同步特性。*/
	public synchronized void add(int num)
	{
		sum=sum+num;
		System.out.println("sum="+sum);
	}
同步函數使用的鎖是this,也就是當前對象。
同步函數和同步代碼塊的區別:
同步函數的鎖是固定的this。
同步代碼塊的鎖可以是任意對象。

但是,建議使用同步代碼塊。



靜態的同步函數使用的鎖是 該函數所屬的字節碼文件對象。
該對象可以用this.getClass()方法獲取,也可以用當前類名.class獲取。

class Cus implements Runnable
{
	private Bank b=new Bank();
	public void run()
	{
		for (int x=0;x<3 ;x++ )
		{
			b.add(100);
		}
	}
}
class DuoXiancheng 
{
	public static void main(String[] args) 
	{
		/*創建線程的目的是爲了開啓一條執行路徑,去運行指定的代碼和其他代碼實現同時運行。
		而運行的指定代碼就是這個執行路徑的任務。
		JVM創建的主線程的任務都定義在了主函數中。
		
		Thread類用於描述線程,線程是需要任務的,所以Thread類也有對任務的描述。
		這個任務就是通過Thread類中的run方法來體現,也就是說。
		run方法就是封裝自定義線程運行任務的函數。
		run方法中定義的就是線程要運行的任務代碼。
		開啓線程是爲了運行指定的代碼,所以只有繼承Thread類,並複寫run方法。
		將運行的代碼定義在run方法中即可。*/
	/*	XianCheng x=new XianCheng("陳奕迅");
		XianCheng c=new XianCheng("黃家駒");
		x.start();//調用線程中的start方法。
		c.start();
		System.out.println("-----------");
		Zi z=new Zi("隨意");
		Zi z1=new Zi("隨便");
		Thread t1= new Thread(z);
		Thread t2=new Thread(z1);
		t1.start();
		t2.start();
		Piao p=new Piao();
		Thread t=new Thread(p);
		Thread t1=new Thread(p);
		Thread t2=new Thread(p);
		Thread t3=new Thread(p);
		t.start();
		t1.start();
		t2.start();
		t3.start();*/
		Cus c=new Cus();
		Thread t1=new Thread(c);
		Thread t2=new Thread(c);
		t1.start();
		t2.start();
	}
}


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