執行緒的通訊
前面學習了用wait/notify的方式進行執行緒通訊。今天學習一種更加強大的執行緒通訊方式condition.condition的強大之處就是可以為執行緒建立不同的condition。然後可以喚醒任意指定阻塞的執行緒。condition之所以能為乙個執行緒建立不同的condition,是因為它也維護著乙個阻塞的條件佇列。它跟aqs等待佇列通過執行緒的等待、喚醒建立關係。
1.每當aqs佇列中的執行緒呼叫condition.await()方法,aqs就會把當前執行緒從佇列中移除,並加入到condition佇列的尾部並阻塞,然後等待喚醒。
2.每當aqs佇列中線程對condition佇列中的某個阻塞執行緒進行了condition.sinal()方法,condition佇列就會把該執行緒從佇列中移除,執行緒加入aqs等待佇列末尾,等待獲取鎖。
通過condition實現多執行緒的消費者、生產者模式來進一步理解:
public
class conditiontest
/*** 每次生產count個產品
* @param count
*/public
void
producer(int count)
int actcount = (count + depots.size()) > size ? (size - depots.size()) : count; //如果生產的數量和現有的數量大於總數,就只生產倉庫剩餘的最大容量數
system.out.println(thread.currentthread().getname() + "執行緒開始生產");
for(int i = 0; i < actcount; i++ )
system.out.println(thread.currentthread().getname() + "生產完畢,當前倉庫有" + depots.size() + "個產品");
notemptycondition.signal();
} catch (interruptedexception e) finally
}public
void
consumer(int count)
int actcount = (depots.size() > count ) ? count : depots.size();//如果當前倉庫剩餘容量大於消費容量,就消費消費個,如果消費的容量比倉庫剩餘容量大,就把剩餘的都消費掉。
system.out.println(thread.currentthread().getname() + "執行緒開始消費");
iteratoriterator = depots.iterator();
while(iterator.hasnext() && actcount > 0 )
system.out.println(thread.currentthread().getname() + "消費完畢,當前倉庫有" + depots.size() + "個產品");
notfullcondition.signal();
} catch (exception e) finally }}
public
static
void
main(string args)
}},"producer-" + i );
thread.start();
}for(int i = 0; i < 30; i++)
}},"consumer-" + i);
thread1.start();}}
}
某一次執行部分結果
producer-20執行緒開始生產
producer-20生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-2執行緒開始消費
cusume-2消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-21執行緒開始生產
producer-21生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-28執行緒開始消費
cusume-28消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-15執行緒開始生產
producer-15生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-11執行緒開始消費
cusume-11消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-24執行緒開始生產
producer-24生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-14執行緒開始消費
cusume-14消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-19執行緒開始生產
producer-19生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-4執行緒開始消費
cusume-4消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-25執行緒開始生產
producer-25生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-15執行緒開始消費
cusume-15消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-8執行緒開始生產
producer-8生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-20執行緒開始消費
cusume-20消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-29執行緒開始生產
producer-29生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-5執行緒開始消費
cusume-5消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-1執行緒開始生產
producer-1生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-0執行緒開始消費
cusume-0消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-26執行緒開始生產
producer-26生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-18執行緒開始消費
cusume-18消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-16執行緒開始生產
producer-16生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-19執行緒開始消費
cusume-19消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-3執行緒開始生產
producer-3生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-12執行緒開始消費
cusume-12消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-7執行緒開始生產
producer-7生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-22執行緒開始消費
cusume-22消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-11執行緒開始生產
producer-11生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-26執行緒開始消費
cusume-26消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-2執行緒開始生產
producer-2生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-1執行緒開始消費
cusume-1消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-28執行緒開始生產
producer-28生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-23執行緒開始消費
cusume-23消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
producer-10執行緒開始生產
producer-10生產完畢,當前倉庫有40個產品
倉庫已經有鏟產品了,可以開始消費了
cusume-27執行緒開始消費
cusume-27消費完畢,當前倉庫有0個產品
當前倉庫為空,等待生產
上面是簡單模擬生產者消費者的例子。當然其中還有很多變化。還有就是用list來做儲存。這個在多執行緒高併發環境下是不安全的等等。以後會學習juc下的集合以及一些併發類。就能寫出越來越安全的生產者消費真模式。 java 多執行緒之通訊
共享堆記憶體變數屬於通訊的一種,今天要介紹的是使用object類中的wait和notify方法進行通訊,可以讓兩個執行緒共同地輪流做一件事 再看object類 object類是所有類的根父類,現在主要介紹wait方法和notify方法 void wait 讓當前執行緒進入等待狀態,直到別的執行緒將其...
JAVA多執行緒之 執行緒池
執行緒池顧名思義,就是乙個放置執行緒的池子。就跟資料庫連線池差不多。執行緒池通過對併發執行緒的控制,能有效的節省系統資源的浪費,提高系統的效能。學習執行緒池,先了解一下執行緒池的乙個基本結構 executor是乙個介面,其中只有乙個方法,就是execute方法。所以executor實際就是乙個執行緒...
Java多執行緒之執行緒安全
當多個執行緒訪問某乙個類 物件或方法時 這個類始終都能表現出正確的行為,那麼這個類 物件或方法 就是執行緒安全的。public class mythread extends thread public static void main string args 結果如下 t1正在執行 4 t1正在執行...