一年又過去了,習(xí)慣上我還是使用陰歷來判別一年,元旦過后,我還沒有想到一年又過去了,但是過完春節(jié),這種感覺就突然特別強(qiáng)烈起來,呵呵,小時(shí)候養(yǎng)成的習(xí)慣,不是說變就能改變的。
在一月份怎么說呢,上半個(gè)月感覺特別累,人也特別敏感,易怒。下半個(gè)月,還是相對(duì)比較輕松的心態(tài),就算是犒勞自己吧。第一二周主要是準(zhǔn)備工作匯報(bào)材料,一群人沒日沒夜地干,就為了把工作匯報(bào)整出色, 還額外新增了許多功能,光說短信吧, 短短3天,就集成進(jìn)了系統(tǒng),這個(gè)不容易啊,每個(gè)人都鉚足了勁,想整點(diǎn)色彩出來,當(dāng)然我其實(shí)也知道,我說過12月會(huì)輕松一點(diǎn),但是12月份沒有輕松過,然后我又說1月份會(huì)輕松一點(diǎn),接著就是更累得一月份,自己也感覺慚愧啊,項(xiàng)目本來工作量太多是一方面,但是更多的,我還是認(rèn)為,管理上面還是存在很大問題,沒有預(yù)見到兩個(gè)重大問題,第一,框架的嚴(yán)重不足,第二,人員培訓(xùn)嚴(yán)重不足,當(dāng)時(shí)對(duì)框架依賴程度過高, 其實(shí)框架在后面幾次致命的變動(dòng),給系統(tǒng)帶來的修改工作量非同一般?。粚?duì)人員的水平估計(jì)過高,也是把所有人包括自己弄得很慘的一個(gè)重要原因,以為經(jīng)過前面的一個(gè)小項(xiàng)目,人員水平應(yīng)該都有很大的提高,滿足一般的項(xiàng)目需求問題不是很大的,但是實(shí)際情況告訴我,從一個(gè)不懂編程到熟練工, 絕對(duì)不是一蹴而就的,就算是勞動(dòng)強(qiáng)度很大的鍛煉,那也需要很長(zhǎng)時(shí)間的,至少也需要一到兩年。我們只用了2個(gè)月,就算是學(xué)了九陽(yáng)神功也沒有那么快啊。當(dāng)然所有的一切責(zé)任歸結(jié)起來,就是項(xiàng)目管理的失敗,風(fēng)險(xiǎn)識(shí)別錯(cuò)誤,一開始的風(fēng)險(xiǎn)識(shí)別就只是考慮時(shí)間緊,業(yè)務(wù)不熟練,根本就沒有考慮到人員的技術(shù)水平,所以后面對(duì)質(zhì)量的忽視的默許,對(duì)人員培養(yǎng)的中斷, 直接導(dǎo)致了最后的一個(gè)大泥潭,當(dāng)然我們現(xiàn)在是甲方,這個(gè)跳蚤還是得自己摘掉的,因?yàn)槟悴皇歉梢黄本妥呷说陌ⅰ?br />
在匯報(bào)后,就開始進(jìn)行年終總結(jié), 呵呵,因?yàn)橛泻芏喔邢耄?jì)劃的三千字,輕易的就達(dá)到,寫得時(shí)候根本就沒有考慮過達(dá)到了。
針對(duì)需要改進(jìn)的內(nèi)容也寫了很多,有幾點(diǎn)特別重要,第一,千萬(wàn)不要深度參與到項(xiàng)目的開發(fā)中去,因?yàn)檫@樣你害了所有人,沒有統(tǒng)籌安排,必然導(dǎo)致更多的問題和混亂,而且這些內(nèi)容遲早要交接出去的,那么,別人接手還是很痛苦,所以從一開始就要把握好自己。第二,計(jì)劃很重要,計(jì)劃要仔細(xì)考慮,不是一拍腦袋,計(jì)劃就出來,完成了很多電子表格,但是這沒有用,有用的計(jì)劃應(yīng)該是討論出來的,是仔細(xì)思考,全盤考慮的結(jié)果。最后,計(jì)劃始終只是計(jì)劃,還需要不斷跟進(jìn),這樣才能逐步逼近目標(biāo)。
下月還有一些計(jì)劃,主要一個(gè)是制定項(xiàng)目管理規(guī)范,很多時(shí)候做到有章可循還是比較好的,最佳實(shí)踐不一定完全適合你,但是你總能受點(diǎn)啟發(fā)吧。日積月累,不就形成了一個(gè)所以得經(jīng)驗(yàn)了嗎?打游戲還講究經(jīng)驗(yàn)值呢,做事為什么就要拒絕經(jīng)驗(yàn)?zāi)亍?br />
第二個(gè),還要把現(xiàn)在的內(nèi)容消化,現(xiàn)在內(nèi)容很多,但老實(shí)說,需要花力氣整合,而且還有些核心功能都不是特別穩(wěn)定,也急切需要穩(wěn)定?,F(xiàn)在一堆所謂的重構(gòu), 但是我一直知道有一句話,沒有最好,只有最合適。其實(shí)對(duì)于軟件也是這樣,優(yōu)化是沒有止境的,但是我們也要有一個(gè)度,再過三個(gè)月,回過頭來看,現(xiàn)在的很多功能和代碼又會(huì)有點(diǎn)像狗屎,因?yàn)槟氵M(jìn)步了。是不是我們?cè)倩獍阉鼈兌贾貥?gòu)一下呢,不一定。首先用戶對(duì)于你的修改是否認(rèn)為一定需要,用的還蠻好的,也總的給我一個(gè)更換的理由吧, 總不能說廠家都從n70換到n73, 我就要換吧。其次,你的時(shí)間和精力允許你這樣做嗎?但是并不是代表我們就什么都不做,一直拒絕新事物,這樣怎么能從量變到質(zhì)變呢,不質(zhì)變,不適應(yīng)新情況了總是要被淘汰的吧,比如小靈通。
所以我想我們每個(gè)人都要習(xí)慣改變,但是要抓住本質(zhì),有一句話“要么改變,要么被改變”。
1, 使用java提供的方法,在jsp或者servlet中都可以
<%
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
%>
2, 使用HTML標(biāo)記,如下面:
<HEAD>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="0">
</HEAD>
轉(zhuǎn)載
http://www.matrix.org.cn/thread.shtml?forum_id=19&view_id=919int、char、double與byte相互轉(zhuǎn)換的程序
//整數(shù)到字節(jié)數(shù)組的轉(zhuǎn)換
public static byte[] intToByte(int number) {
int temp = number;
byte[] b=new byte[4];
for (int i=b.length-1;i>-1;i--){
b[i] = new Integer(temp&0xff).byteValue(); //將最高位保存在最低位
temp = temp >> 8; //向右移8位
}
return b;
}
//字節(jié)數(shù)組到整數(shù)的轉(zhuǎn)換
public static int byteToInt(byte[] b) {
int s = 0;
for (int i = 0; i < 3; i++) {
if (b[i] >= 0)
s = s + b[i];
else
s = s + 256 + b[i];
s = s * 256;
}
if (b[3] >= 0) //最后一個(gè)之所以不乘,是因?yàn)榭赡軙?huì)溢出
s = s + b[3];
else
s = s + 256 + b[3];
return s;
}
//字符到字節(jié)轉(zhuǎn)換
public static byte[] charToByte(char ch){
int temp=(int)ch;
byte[] b=new byte[2];
for (int i=b.length-1;i>-1;i--){
b[i] = new Integer(temp&0xff).byteValue(); //將最高位保存在最低位
temp = temp >> 8; //向右移8位
}
return b;
}
//字節(jié)到字符轉(zhuǎn)換
public static char byteToChar(byte[] b){
int s=0;
if(b[0]>0)
s+=b[0];
else
s+=256+b[0];
s*=256;
if(b[1]>0)
s+=b[1];
else
s+=256+b[1];
char ch=(char)s;
return ch;
}
//浮點(diǎn)到字節(jié)轉(zhuǎn)換
public static byte[] doubleToByte(double d){
byte[] b=new byte[8];
long l=Double.doubleToLongBits(d);
for(int i=0;i<b.length;i++){
b[i]=new Long(l).byteValue();
l=l>>8;
}
return b;
}
//字節(jié)到浮點(diǎn)轉(zhuǎn)換
public static double byteToDouble(byte[] b){
long l;
l=b[0];
l&=0xff;
l|=((long)b[1]<<8);
l&=0xffff;
l|=((long)b[2]<<16);
l&=0xffffff;
l|=((long)b[3]<<24);
l&=0xffffffffl;
l|=((long)b[4]<<32);
l&=0xffffffffffl;
l|=((long)b[5]<<40);
l&=0xffffffffffffl;
l|=((long)b[6]<<48);
l|=((long)b[7]<<56);
return Double.longBitsToDouble(l);
}
--
先從線程的創(chuàng)建說起.線程的創(chuàng)建一共有兩種形式:
--------------------------------------------------------------------------------
一種是繼承自Thread類.Thread 類是一個(gè)具體的類,即不是抽象類,該類封裝了線程的行為.要?jiǎng)?chuàng)建一個(gè)線程,程序員必須創(chuàng)建一個(gè)從 Thread 類導(dǎo)出的新類.程序員通過覆蓋 Thread 的 run() 函數(shù)來完成有用的工作.用戶并不直接調(diào)用此函數(shù);而是通過調(diào)用 Thread 的 start() 函數(shù),該函數(shù)再調(diào)用 run(). 例如:
public class Test extends Thread{ public Test(){ } public static void main(String args[]){ Test t1 = new Test(); Test t2 = new Test(); t1.start(); t2.start(); } public void run(){ //do thread's things } }
--------------------------------------------------------------------------------
另一種是實(shí)現(xiàn)Runnable接口,此接口只有一個(gè)函數(shù),run(),此函數(shù)必須由實(shí)現(xiàn)了此接口的類實(shí)現(xiàn). 例如:
public class Test implements Runnable{ Thread thread1; Thread thread2; public Test(){ thread1 = new Thread(this,"1"); thread2 = new Thread(this,"2"); } public static void main(String args[]){ Test t = new Test(); t.startThreads(); } public void run(){ //do thread's things } public void startThreads(){ thread1.start(); thread2.start(); } }
兩種創(chuàng)建方式看起來差別不大,但是弄不清楚的話,也許會(huì)將你的程序弄得一團(tuán)糟.兩者區(qū)別有以下幾點(diǎn):
1.當(dāng)你想繼承某一其它類時(shí),你只能用后一種方式.
2.第一種因?yàn)槔^承自Thread,只創(chuàng)建了自身對(duì)象,但是在數(shù)量上,需要幾個(gè)線程,就得創(chuàng)建幾個(gè)自身對(duì)象;第二種只創(chuàng)建一個(gè)自身對(duì)象,卻創(chuàng)建幾個(gè)Thread對(duì)象.而兩種方法重大的區(qū)別就在于此,請(qǐng)你考慮:如果你在第一種里創(chuàng)建數(shù)個(gè)自身對(duì)象并且start()后,你會(huì)發(fā)現(xiàn)好像synchronized不起作用了,已經(jīng)加鎖的代碼塊或者方法居然同時(shí)可以有幾個(gè)線程進(jìn)去,而且同樣一個(gè)變量,居然可以有好幾個(gè)線程同時(shí)可以去更改它.(例如下面的代碼)這是因?yàn)?在這個(gè)程序中,雖然你起了數(shù)個(gè)線程,可是你也創(chuàng)建了數(shù)個(gè)對(duì)象,而且,每個(gè)線程對(duì)應(yīng)了每個(gè)對(duì)象也就是說,每個(gè)線程更改和占有的對(duì)象都不一樣,所以就出現(xiàn)了同時(shí)有幾個(gè)線程進(jìn)入一個(gè)方法的現(xiàn)象,其實(shí),那也不是一個(gè)方法,而是不同對(duì)象的相同的方法.所以,這時(shí)候你要加鎖的話,只能將方法或者變量聲明為靜態(tài),將static加上后,你就會(huì)發(fā)現(xiàn),線程又能管住方法了,同時(shí)不可能有兩個(gè)線程進(jìn)入同樣一個(gè)方法,那是因?yàn)?現(xiàn)在不是每個(gè)對(duì)象都擁有一個(gè)方法了,而是所有的對(duì)象共同擁有一個(gè)方法,這個(gè)方法就是靜態(tài)方法.
而你如果用第二種方法使用線程的話,就不會(huì)有上述的情況,因?yàn)榇藭r(shí),你只創(chuàng)建了一個(gè)自身對(duì)象,所以,自身對(duì)象的屬性和方法對(duì)于線程來說是共有的.
因此,我建議,最好用后一種方法來使用線程.
public class mainThread extends Thread{ int i=0; public static void main(String args[]){ mainThread m1 = new mainThread(); mainThread m2 = new mainThread(); mainThread m3 = new mainThread(); mainThread m4 = new mainThread(); mainThread m5 = new mainThread(); mainThread m6 = new mainThread(); m1.start(); m2.start(); m3.start(); m4.start(); m5.start(); m6.start(); } public synchronized void t1(){ i=++i; try{
|
Thread.sleep(500);
}
catch(Exception e){}
//每個(gè)線程都進(jìn)入各自的t1()方法,分別打印各自的i
System.out.println(Thread.currentThread().getName()+" "+i);
}
public void run(){
synchronized(this){
while (true) {
t1();
}
}
}
}
--------------------------------------------------------------------------------
下面我們來講synchronized的4種用法吧:
1.方法聲明時(shí)使用,放在范圍操作符(public等)之后,返回類型聲明(void等)之前.即一次只能有一個(gè)線程進(jìn)入該方法,其他線程要想在此時(shí)調(diào)用該方法,只能排隊(duì)等候,當(dāng)前線程(就是在synchronized方法內(nèi)部的線程)執(zhí)行完該方法后,別的線程才能進(jìn)入.
例如:
public synchronized void synMethod() {
//方法體
}
2.對(duì)某一代碼塊使用,synchronized后跟括號(hào),括號(hào)里是變量,這樣,一次只有一個(gè)線程進(jìn)入該代碼塊.例如:
public int synMethod(int a1){
synchronized(a1) {
//一次只能有一個(gè)線程進(jìn)入
}
}
3.synchronized后面括號(hào)里是一對(duì)象,此時(shí),線程獲得的是對(duì)象鎖.例如:
public class MyThread implements Runnable {
public static void main(String args[]) {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt, "t1");
Thread t2 = new Thread(mt, "t2");
Thread t3 = new Thread(mt, "t3");
Thread t4 = new Thread(mt, "t4");
Thread t5 = new Thread(mt, "t5");
Thread t6 = new Thread(mt, "t6");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName());
}
}
}
對(duì)于3,如果線程進(jìn)入,則得到對(duì)象鎖,那么別的線程在該類所有對(duì)象上的任何操作都不能進(jìn)行.在對(duì)象級(jí)使用鎖通常是一種比較粗糙的方法.為什么要將整個(gè)對(duì)象都上鎖,而不允許其他線程短暫地使用對(duì)象中其他同步方法來訪問共享資源?如果一個(gè)對(duì)象擁有多個(gè)資源,就不需要只為了讓一個(gè)線程使用其中一部分資源,就將所有線程都鎖在外面.由于每個(gè)對(duì)象都有鎖,可以如下所示使用虛擬對(duì)象來上鎖:
class FineGrainLock {
MyMemberClass x, y;
Object xlock = new Object(), ylock = new Object();
public void foo() {
synchronized(xlock) {
//access x here
}
//do something here - but don't use shared resources
synchronized(ylock) {
//access y here
}
}
public void bar() {
synchronized(this) {
//access both x and y here
}
//do something here - but don't use shared resources
}
}
4.synchronized后面括號(hào)里是類.例如:
class ArrayWithLockOrder{
private static long num_locks = 0;
private long lock_order;
private int[] arr;
public ArrayWithLockOrder(int[] a)
{
arr = a;
synchronized(ArrayWithLockOrder.class) {//-----------------------------------------這里
num_locks++; // 鎖數(shù)加 1.
lock_order = num_locks; // 為此對(duì)象實(shí)例設(shè)置唯一的 lock_order.
}
}
public long lockOrder()
{
return lock_order;
}
public int[] array()
{
return arr;
}
}
class SomeClass implements Runnable
{
public int sumArrays(ArrayWithLockOrder a1,
ArrayWithLockOrder a2)
{
int value = 0;
ArrayWithLockOrder first = a1; // 保留數(shù)組引用的一個(gè)
ArrayWithLockOrder last = a2; // 本地副本.
int size = a1.array().length;
if (size == a2.array().length)
{
if (a1.lockOrder() > a2.lockOrder()) // 確定并設(shè)置對(duì)象的鎖定
{ // 順序.
first = a2;
last = a1;
}
synchronized(first) { // 按正確的順序鎖定對(duì)象.
synchronized(last) {
int[] arr1 = a1.array();
int[] arr2 = a2.array();
for (int i=0; i<size; i++)
value += arr1[i] + arr2[i];
}
}
}
return value;
}
public void run() {
//...
}
}
對(duì)于4,如果線程進(jìn)入,則線程在該類中所有操作不能進(jìn)行,包括靜態(tài)變量和靜態(tài)方法,實(shí)際上,對(duì)于含有靜態(tài)方法和靜態(tài)變量的代碼塊的同步,我們通常用4來加鎖.
以上4種之間的關(guān)系:
鎖是和對(duì)象相關(guān)聯(lián)的,每個(gè)對(duì)象有一把鎖,為了執(zhí)行synchronized語(yǔ)句,線程必須能夠獲得synchronized語(yǔ)句中表達(dá)式指定的對(duì)象的鎖,一個(gè)對(duì)象只有一把鎖,被一個(gè)線程獲得之后它就不再擁有這把鎖,線程在執(zhí)行完synchronized語(yǔ)句后,將獲得鎖交還給對(duì)象.
在方法前面加上synchronized修飾符即可以將一個(gè)方法聲明為同步化方法.同步化方法在執(zhí)行之前獲得一個(gè)鎖.如果這是一個(gè)類方法,那么獲得的鎖是和聲明方法的類相關(guān)的Class類對(duì)象的鎖.如果這是一個(gè)實(shí)例方法,那么此鎖是this對(duì)象的鎖.
--------------------------------------------------------------------------------
下面談一談一些常用的方法:
wait(),wait(long),notify(),notifyAll()等方法是當(dāng)前類的實(shí)例方法,
wait()是使持有對(duì)象鎖的線程釋放鎖;
wait(long)是使持有對(duì)象鎖的線程釋放鎖時(shí)間為long(毫秒)后,再次獲得鎖,wait()和wait(0)等價(jià);
notify()是喚醒一個(gè)正在等待該對(duì)象鎖的線程,如果等待的線程不止一個(gè),那么被喚醒的線程由jvm確定;
notifyAll是喚醒所有正在等待該對(duì)象鎖的線程.
在這里我也重申一下,我們應(yīng)該優(yōu)先使用notifyAll()方法,因?yàn)閱拘阉芯€程比喚醒一個(gè)線程更容易讓jvm找到最適合被喚醒的線程.
對(duì)于上述方法,只有在當(dāng)前線程中才能使用,否則報(bào)運(yùn)行時(shí)錯(cuò)誤java.lang.IllegalMonitorStateException: current thread not owner.
--------------------------------------------------------------------------------
下面,我談一下synchronized和wait(),notify()等的關(guān)系:
1.有synchronized的地方不一定有wait,notify
2.有wait,notify的地方必有synchronized.這是因?yàn)閣ait和notify不是屬于線程類,而是每一個(gè)對(duì)象都具有的方法,而且,這兩個(gè)方法都和對(duì)象鎖有關(guān),有鎖的地方,必有synchronized.
另外,請(qǐng)注意一點(diǎn):如果要把notify和wait方法放在一起用的話,必須先調(diào)用notify后調(diào)用wait,因?yàn)槿绻{(diào)用完wait,該線程就已經(jīng)不是current thread了.如下例:
/**
* Title: Jdeveloper's Java Projdect
* Description: n/a
* Copyright: Copyright ? 2001
* Company: soho http://www.ChinaJavaWorld.com
* @author jdeveloper@21cn.com
* @version 1.0
*/
import java.lang.Runnable;
import java.lang.Thread;
public class DemoThread
implements Runnable {
public DemoThread() {
TestThread testthread1 = new TestThread(this, "1");
TestThread testthread2 = new TestThread(this, "2");
testthread2.start();
testthread1.start();
}
public static void main(String[] args) {
DemoThread demoThread1 = new DemoThread();
}
public void run() {
TestThread t = (TestThread) Thread.currentThread();
try {
if (!t.getName().equalsIgnoreCase("1")) {
synchronized (this) {
wait();
}
}
while (true) {
System.out.println("@time in thread" + t.getName() + "=" +
t.increaseTime());
if (t.getTime() % 10 == 0) {
synchronized (this) {
System.out.println("****************************************");
notify();
if (t.getTime() == 100)
break;
wait();
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
class TestThread
extends Thread {
private int time = 0;
public TestThread(Runnable r, String name) {
super(r, name);
}
public int getTime() {
return time;
}
public int increaseTime() {
return++time;
}
}
下面我們用生產(chǎn)者/消費(fèi)者這個(gè)例子來說明他們之間的關(guān)系:
public class test {
public static void main(String args[]) {
Semaphore s = new Semaphore(1);
Thread t1 = new Thread(s, "producer1");
Thread t2 = new Thread(s, "producer2");
Thread t3 = new Thread(s, "producer3");
Thread t4 = new Thread(s, "consumer1");
Thread t5 = new Thread(s, "consumer2");
Thread t6 = new Thread(s, "consumer3");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
class Semaphore
implements Runnable {
private int count;
public Semaphore(int n) {
this.count = n;
}
public synchronized void acquire() {
while (count == 0) {
try {
wait();
}
catch (InterruptedException e) {
//keep trying
}
}
count--;
}
public synchronized void release() {
while (count == 10) {
try {
wait();
}
catch (InterruptedException e) {
//keep trying
}
}
count++;
notifyAll(); //alert a thread that's blocking on this semaphore
}
public void run() {
while (true) {
if (Thread.currentThread().getName().substring(0,8).equalsIgnoreCase("consumer")) {
acquire();
}
else if (Thread.currentThread().getName().substring(0,8).equalsIgnoreCase("producer")) {
release();
}
System.out.println(Thread.currentThread().getName() + " " + count);
}
}
}
生產(chǎn)者生產(chǎn),消費(fèi)者消費(fèi),一般沒有沖突,但當(dāng)庫(kù)存為0時(shí),消費(fèi)者要消費(fèi)是不行的,但當(dāng)庫(kù)存為上限(這里是10)時(shí),生產(chǎn)者也不能生產(chǎn).請(qǐng)好好研讀上面的程序,你一定會(huì)比以前進(jìn)步很多.
上面的代碼說明了synchronized和wait,notify沒有絕對(duì)的關(guān)系,在synchronized聲明的方法,代碼塊中,你完全可以不用wait,notify等方法,但是,如果當(dāng)線程對(duì)某一資源存在某種爭(zhēng)用的情況下,你必須適時(shí)得將線程放入等待或者喚醒.
------------------------
在java中,每個(gè)對(duì)象只有一個(gè)相應(yīng)的monitor,一個(gè)mutex,而每一個(gè)monitor都可以有多個(gè)“doors”可以進(jìn)入,即,同一個(gè)monitor中被守護(hù)的代碼可以在不同的地方,因?yàn)橥粋€(gè)對(duì)象可以出現(xiàn)在不同的代碼段,只要mutex鎖定的對(duì)象是同一個(gè),每個(gè)入口都用Synchronized關(guān)鍵字表明,當(dāng)一個(gè)線程通過了Synchronized關(guān)鍵字,它就所住了該monitor所有的doors。因此是mutex定義了monitor而不是代碼。
另外,wait和notify、notifyAll都是Object的方法,使用wait必須是The current thread must own this object's monitor
wait
public final void wait()
throws InterruptedExceptionCauses current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.
Throws:
IllegalMonitorStateException - if the current thread is not the owner of the object's monitor.
InterruptedException - if another thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
See Also:
notify(), notifyAll()
A thread becomes the owner of the object's monitor in one of three ways:
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes on the object.
For objects of type Class, by executing a synchronized static method of that class.
Only one thread at a time can own an object's monitor.