淺談線程


定義與解釋:

          進程:是一個正在執行中的程序。

         每一個進程執行都有一個執行順序。該順序是一個執行路徑,或者叫一個控制單元。

         線程:就是進程中的一個獨立的控制單元。

         線程在控制着進程的執行。

           一個進程中至少有一個線程。
           1.    如何在自定義的代碼中,自定義一個線程呢?
                  通過對api的查找,java已經提供了對線程這類事物的描述。就Thread類。

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

------------------------------------------------------------------------------------------------------------------------------------------

步驟:  

              1. 定義類繼承Thread。
              2. 複寫Thread類中的run方法。
                   目的:將自定義代碼存儲在run方法。讓線程運行。
              3. 調用線程的start方法,
          該方法兩個作用:啓動線程,調用run方法。
          爲什麼要覆蓋run方法呢?
          Thread類用於描述線程。
          該類就定義了一個功能,用於存儲線程要運行的代碼。該存儲功能就是run方法。
          也就是說Thread類中的run方法,用於存儲線程要運行的代碼。

示例:


class Demo extends Thread
{
	public void run()
	{
		for(int x=0; x<60; x++)
			System.out.println("demo run----"+x);
	}
}
class ThreadDemo 
{
	public static void main(String[] args) 
	{
		//for(int x=0; x<4000; x++)
		//System.out.println("Hello World!");


		Demo d = new Demo();//創建好一個線程。
		d.start();//開啓線程並執行該線程的run方法。
		//d.run();//僅僅是對象調用方法。而線程創建了,並沒有運行。
	
	}
}

練習:

          創建兩個線程,和主線程交替運行。
------------------------------------------------------------------------------------------------------------------------------------------
原來線程都有自己默認的名稱。
Thread-編號 該編號從0開始。
static Thread currentThread():獲取當前線程對象。
getName(): 獲取線程名稱。
設置線程名稱:setName或者構造函數。

示例:

class Test extends Thread
{
	//private String name;
	Test(String name)
	{
		//this.name = name;
		super(name);
	}
	public void run()
	{
		for(int x=0; x<60; x++)
		{
			System.out.println((Thread.currentThread()==this)+"..."+this.getName()+" run..."+x);
		}
	}

}
class ThreadTest 
{
	public static void main(String[] args) 
	{
		Test t1 = new Test("one---");
		Test t2 = new Test("two+++");
		t1.start();
		t2.start();
	for(int x=0; x<60; x++)
		{
			System.out.println("main....."+x);
		}
	}
}

創建線程的第二種方式:實現Runnable接口

------------------------------------------------------------------------------------------------------------------------------------------

步驟:

           1. 定義類實現Runnable接口 

           2. 覆蓋Runnable接口中的run方法。

              將線程要運行的代碼存放在該run方法中。

          3. 通過Thread類建立線程對象。

          4. 將Runnable接口的子類對象作爲實際參數傳遞給Thread類的構造函數。

             爲什麼要將Runnable接口的子類對象傳遞給Thread的構造函數。

             因爲,自定義的run方法所屬的對象是Runnable接口的子類對象。 

             所以要讓線程去指定指定對象的run方法。就必須明確該run方法所屬對象。

         5. 調用Thread類的start方法開啓線程並調用Runnable接口子類的run方法。

實現方式和繼承方式有什麼區別呢?
實現方式好處:避免了單繼承的侷限性。
在定義線程時,建立使用實現方式。

兩種方式區別:

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

示例:

------------------------------------------------------------------------------------------------------------------------------------------

         需求:簡單的賣票程序。      多個窗口同時買票。

class Ticket implements Runnable//extends Thread
{
	private  int tick = 100;
	public void run()
	{
		while(true)
		{
			if(tick>0)
			{
				System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
			}
		}
	}
}
class  TicketDemo
{
	public static void main(String[] args) 
	{
		Ticket t = new Ticket();
		Thread t1 = new Thread(t);//創建了一個線程;
		Thread t2 = new Thread(t);//創建了一個線程;
		Thread t3 = new Thread(t);//創建了一個線程;
		Thread t4 = new Thread(t);//創建了一個線程;
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}




多線程的安全問題

------------------------------------------------------------------------------------------------------------------------------------------


問題的原因:

當多條語句在操作同一個線程共享數據時,一個線程對多條語句只執行了一部分,還沒有執行完,
另一個線程參與進來執行。導致共享數據的錯誤。

解決辦法:

對多條操作共享數據的語句,只能讓一個線程都執行完。在執行過程中,其他線程不可以參與執行。

        Java對於多線程的安全問題提供了專業的解決方式。

       就是同步代碼塊。

       synchronized(對象)
       {
    需要被同步的代碼
       }


       對象如同鎖。持有鎖的線程可以在同步中執行。
      沒有持有鎖的線程即使獲取cpu的執行權,也進不去,因爲沒有獲取鎖。
      火車上的衛生間---經典。

同步的前提:

      1. 必須要有兩個或者兩個以上的線程。
      2. 必須是多個線程使用同一個鎖。
       必須保證同步中只能有一個線程在運行。

好處:解決了多線程的安全問題。
弊端:多個線程需要判斷鎖,較爲消耗資源,

示例:

------------------------------------------------------------------------------------------------------------------------------------------

class Ticket implements Runnable
{
	private  int tick = 1000;
	Object obj = new Object();
	public void run()
	{
		while(true)
		{
			synchronized(obj)//同步代碼塊
			{
				if(tick>0)
				{
					//try{Thread.sleep(10);}catch(Exception e){}
					System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
				}
			}
		}
	}
}




class  TicketDemo2
{
	public static void main(String[] args) 
	{


		Ticket t = new Ticket();


		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		Thread t4 = new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		t4.start();

	}
}


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