線程的概念是什麼?線程之間是如何通信的?
線程是進程中的一個執行單元,同一個進程中的各個線程對應於一組CPU指令、一組CPU寄存器以及一堆棧。進程本來就具有動態的含義,然而實質上是通過線程來執行體現的,從這個意義上說,Windows中進程的動態性意義已經不是很明顯了,只算是給程序所佔的資源劃定一個範圍而已,真正具有動態性意義的是線程。
其實,Java提供了3個非常重要的方法來巧妙地解決線程間的通信問題。這3個方法分別是:wait()、notify()和notifyAll()。它們都是Object類的最終方法,因此每一個類都默認擁有它們。
雖然所有的類都默認擁有這3個方法,但是只有在synchronized關鍵字作用的範圍內,並且是同一個同步問題中搭配使用這3個方法時纔有實際的意義。
這些方法在Object類中聲明的語法格式如下所示:
- final void wait() throws InterruptedExceptionfinal void notify()final void notifyAll()
其中,調用wait()方法可以使調用該方法的線程釋放共享資源的鎖,然後從運行態退出,進入等待隊列,直到被再次喚醒。而調用notify()方法可以喚醒等待隊列中第一個等待同一共享資源的線程,並使該線程退出等待隊列,進入可運行態。調用notifyAll()方法可以使所有正在等待隊列中等待同一共享資源的線程從等待狀態退出,進入可運行狀態,此時,優先級最高的那個線程最先執行。顯然,利用這些方法就不必再循環檢測共享資源的狀態,而是在需要的時候直接喚醒等待隊列中的線程就可以了。這樣不但節省了寶貴的CPU資源,也提高了程序的效率。
由於wait()方法在聲明的時候被聲明爲拋出InterruptedException異常,因此,在調用wait()方法時,需要將它放入try…catch代碼塊中。此外,使用該方法時還需要把它放到一個同步代碼段中,否則會出現如下異常:
- "java.lang.IllegalMonitorStateException: current thread not owner"
這些方法是不是就可以實現線程間的通信了呢?下面將通過多線程同步的模型:生產者和消費者問題來說明怎樣通過程序解決多線程間的通信問題。
案例:線程的通信
案例說明
下面這個程序演示了多個線程之間進行通信的具體實現過程。程序中用到了4個類,其中ShareData類用來定義共享數據和同步方法。在同步方法中調用了wait()方法和notify()方法,並通過一個信號量來實現線程間的消息傳遞。
實現過程
Java代碼
//CommunicationDemo.java 描述:生產者和消費者之間的消息傳遞過程
class ShareData
{
private char c;
private boolean isProduced = false; // 信號量
public synchronized void putShareChar(char c) // 同步方法putShareChar()
{
if (isProduced) // 如果產品還未消費,則生產者等待
{
try{wait(); // 生產者等待
}catch(InterruptedException e){
e.printStackTrace();
}
}
this.c = c;
isProduced = true; // 標記已經生產
notify(); // 通知消費者已經生產,可以消費
}
public synchronized char getShareChar() // 同步方法getShareChar()
{
if (!isProduced) // 如果產品還未生產,則消費者等待
{
try
{
wait(); // 消費者等待
}catch(InterruptedException e){
e.printStackTrace();
}
}
isProduced = false; // 標記已經消費
notify(); // 通知需要生產
return this.c;
}
}
class Producer extends Thread // 生產者線程
{
private ShareData s;
Producer(ShareData s)
{
this.s = s;
}
public void run()
{
for (char ch = ''A''; ch <= ''D''; ch++)
{
try
{
Thread.sleep((int)(Math.random()*3000));
}catch(InterruptedException e){
e.printStackTrace();
}
s.putShareChar(ch); // 將產品放入倉庫
System.out.println(ch + " is produced by Producer.");
}
}
}
class Consumer extends Thread // 消費者線程
{
private ShareData s;
Consumer(ShareData s)
{
this.s = s;
}
public void run()
{
char ch;
do{
try
{
Thread.sleep((int)(Math.random()*3000));
}catch(InterruptedException e){
e.printStackTrace();
}
ch = s.getShareChar(); // 從倉庫中取出產品
System.out.println(ch + " is consumed by Consumer. ");
}while (ch != ''D'');
}
}
class CommunicationDemo
{
public static void main(String[] args)
{
ShareData s = new ShareData();
new Consumer(s).start();
new Producer(s).start();
}
}
轉自: http://hi.baidu.com/java_shs/blog/item/57ead73190e594ac5fdf0e3e.html