1. 程式人生 > >[Java][實現多執行緒的三種方式]

[Java][實現多執行緒的三種方式]

目錄

本系列學習筆記簡介

傳智播客的畢向東Java基礎教程是免費公開的一份面向初學者的Java學習教程。在我學習畢老師的Java基礎教程過程中,苦於其並沒有附帶練習題,總覺得學的‘輕飄飄’的,所以決定每天看完的一些內容,總在接下來的幾天裡找一些時間寫下來,看看自己還記得多少,看看自己哪些知識點理解的不透徹。希望本系列學習筆記在幫助自己理清思路,理順知識點的同時,也能夠幫助其他在學習Java的同學。歡迎大家在評論區討論相關內容。

多執行緒的繼承Thread類實現

程序執行緒簡介

程序可以認為是一個正在執行中的程式,你開啟工作管理員就可以看到程序。而執行緒是這個程序中,為了完成一些任務而相互獨立進行的程式碼集合,比如你在360安全衛士中開啟安全檢查的同時又可以清掃垃圾,這時你就開啟了兩個執行緒。

多執行緒賣票介紹

我們這裡通過一個賣票例子來講解多執行緒的繼承Thread類實現。我們假設共有100張編號為1到100的票,在命令列列印一個數字就視為賣出了對應編號的票,我們首先採用繼承Thread類來實現。
思路:建立一個類來繼承Thread類,在子類中重寫run()方法來覆蓋父類Thread中的run()方法。

程式碼塊

錯誤程式碼塊
class Ticket extends Thread
{
	private int num = 100;
	public void run()
	{
		while(true)
		{
			if(num>0)
				System.out.println(Thread.currentThread().getName()+"....."+"num="+num--);
		}
	}
}
class TicketDemo 
{
	public static void main(String[] args) 
	{
		Ticket t1 = new Ticket(
); Ticket t2 = new Ticket(); t1.start(); t2.start(); } }

上述程式碼的部分執行結果為:
命令列結果
我們看到執行緒0與執行緒1賣出了同樣的票號,這是我們不希望看到的,這100號座位旅客0坐還是旅客1坐合適啊?究其原因,是因為我們new了兩個Ticket物件,每生成一個Ticket物件,JVM虛擬機器的堆記憶體中都會有屬於該物件的成員變數num=100,所以num- -的時候每個票號都會出現兩次。我們可以選擇把num變為靜態變數,這樣它就會被JVM儲存在方法區中,被Ticket物件所共享。

正確程式碼塊
class Ticket extends Thread
{
	private static int num = 100;//我們只是在這裡加上了static關鍵字
	public void run()
	{
		while(true)
		{
			if(num>0)
				System.out.println(Thread.currentThread().getName()+"....."+"num="+num--);
		}
	}
}
class TicketDemo 
{
	public static void main(String[] args) 
	{
		Ticket t1 = new Ticket();
		Ticket t2 = new Ticket();
		t1.start();
		t2.start();
    }
}

注意:這個所謂的正確程式碼塊,還是存在安全隱患的,因為如果執行緒0執行到num=1到了判斷語句之後,這時如果執行緒1進來,那麼會輸出Thread=1…num=1,隨後切換到執行緒0,輸出就會為Thread=0…num=0

通過介面Runnable實現多執行緒

由於Java不允許多繼承,所以當一個類已經有父類時就不能夠繼承Thread類了,這時要通過介面Runnable實現多執行緒。使用實現介面Runnable的物件建立執行緒,當啟動執行緒時,在獨立執行的執行緒中就會呼叫物件的run方法。

程式碼塊

class ThreadDemo 
{
	public static void main(String[] args) 
	{
		Ticket t = new Ticket();
		// 使用實現Runnable介面的物件建立一個執行緒
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		//啟動該執行緒,將導致在獨立執行的執行緒中呼叫該物件的run方法
		t1.start();
		t2.start();
	}
}
class Ticket implements Runnable
{
	public int num=100;
	public void run()
	{
		while(true)
		{
			if(num>0)
			System.out.println(Thread.currentThread().getName()+"..."+num--);
		}
	}
}

命令列執行結果為

最後要注意的幾點:
1.上述實現多執行緒是不安全的,還需要通過同步關鍵字synchronized來保證安全。
2.實現多執行緒常見的有三種方式,這裡介紹了通過繼承Thread類實現,通過實現介面Runnable實現,最後一種我們有機會再說。