一、採用傳統的方法
/**
* 經典面試題:寫乙個固定容量的容器,擁有put和get方法,以及getcount方法
* 能夠支援2個生產者執行緒以及10個消費者執行緒的阻塞呼叫
* * 點:生產者消費者模式
* * 如果呼叫 get方法時,容器為空,get方法就需要阻塞等待
* 如果呼叫 put方法時,容器滿了,put方法就需要阻塞等待
* * 實現方式:
* 1. wait/notify
* 2. condition
*/public class mycontainer1 catch (interruptedexception e)
}// 否則 put
list.add(t);
++count;
this.notifyall(); // 通知消費者執行緒,可以消費了
// 【這裡為什麼呼叫 notifyall 而不是 notify ?】
}public synchronized t get() catch (interruptedexception e)
}// 否則獲取
t t = list.removefirst();
count--;
this.notifyall(); // 通知生產者執行緒生產
return t;
}}/*
為什麼使用while 而不是使用 if ???
在與wait()的配合中,百分之99的程式都是與while而不是if結合使用。
上述**中,在容器已滿的情況下,put方法會wait等待,當容器中的元素被消費者消費了一部分,就會喚醒所有put方法,
put方法會繼續向下執行,直接執行list.add(t),那麼多個生產者執行緒執行list.add() 就有可能出現資料一致性的問題。
如果使用while則會迴圈判斷,就避免了這些問題。
不是有鎖嗎?為什麼會需要迴圈判斷?
wait之後,鎖就會失去,再次被喚醒時,並且得到鎖之後,**是從list.add()開始執行的**,會無判斷直接加入到容器中。
為什麼呼叫 notifyall 而不是 notify ?
因為notify有可能再次叫醒乙個生產者執行緒
*/
二、用reentranlock
/**
* 經典面試題:寫乙個固定容量的容器,擁有put和get方法,以及getcount方法
* 能夠支援2個生產者執行緒以及10個消費者執行緒的阻塞呼叫
* * 點:生產者消費者模式
* * 如果呼叫 get方法時,容器為空,get方法就需要阻塞等待
* 如果呼叫 put方法時,容器滿了,put方法就需要阻塞等待
* * 實現方式:
* 1. wait/notify
* 2. condition
* * * 使用lock和condition實現,可以精確喚醒某些執行緒
*/public class mycontainer2
list.add(t);
++count;
consumer.signalall();
} catch (interruptedexception e) finally
}public synchronized t get()
} catch (interruptedexception e) finally
t t = list.removefirst();
count--;
producer.signalall();
return t;
}public static void main(string args)
}, "c_" + i ).start();
}try catch (interruptedexception e)
for (int i = 0; i < 2; i++)
}, "p_" + i).start();}}
}
高併發同步類容器
比如vector hashtable treemap 支援排序 原理是在所有公共方法上加synchronized關鍵字 高併發不用 再併發修改 迭代過程中併發修改了內容 的情況下要加鎖保護操作,否則會報concurrentmodificationexception。copyonwritearrayl...
馬士兵高併發程式設計筆記二之容器讀寫同步
實現乙個容器,提供兩個方法,add,size,寫兩個執行緒,執行緒1新增10個元素到容器中,執行緒2實現監控元素的個數,當個數到5個時,執行緒2給出提示並結束 public class mycontainer2 public intsize public static void main strin...
同步容器與併發容器
同步容器 可以簡單地理解為通過synchronized來實現同步的容器,如果有多個執行緒呼叫同步容器的方法,它們將會序列執行。比如vector,hashtable 早起jdk的一部分 及collections.synchronized 等方法返回的容器。可以通過檢視vector,hashtable等...