需求
我們的程式想要實現這樣的乙個功能,兩個執行緒,乙個不斷往乙個容器加資料,乙個不斷從這個容器取資料。
設計的問題
我們的第乙個問題是,如果容器滿了怎麼辦,空了又怎麼。解決的辦法是使用wait()和notify()。思路是當容器滿或空時,對應的執行緒就應該停下了,等到不空或者不滿的時候再繼續。顯然wait()和notify()可以很好的實現。當空時,暫停取,使用wait(),新增執行緒新增了後就不空了,就可以使用notify()喚醒取的執行緒了。滿的時候也是一樣的。
sleep()和wait()的區別
暫停也可用sleep(),為什麼不用sleep()呢?首先是我們不知道停多久,有notify()配合使用才方便。sleep()和wait()有乙個重要的區別是,sleep()不會讓出物件鎖。我們寫個例子來證明下:
class lock
public synchronized void
sleeptest() catch (interruptedexception e)
}}class print implements runnable
@override
public
void
run()
}class sleeptest implements runnable
@override
public
void
run()
}public
class sleepandwait
}
輸出的結果是,輸出了sleeped 2 second,等待兩秒後,才可以看到輸出的100個thread-1。如果把synchronized去掉,也就是不加鎖,thread-1會立即輸出不會等兩秒。這裡證明sleep是不會讓出物件鎖的。
非常有用的執行緒圖
消費者例項
這是容器,使用乙個類似棧的容器
public
class stack catch (interruptedexception e)
}this.notify();
container[top]=a;
top++;
system.out.println(thread.currentthread().getname()+"入棧的元素"+a);
}public synchronized char
pop() catch (interruptedexception e)
}this.notify();
top--;
system.out.println(thread.currentthread().getname()+"出棧的元素:"+container[top]);
return container[top];}}
生產者
public
class
producer
implements
runnable
@override
public
void
run()}}
消費者
public
class
consumer
implements
runnable
@override
public
void
run() catch (exception e) }}
主線程
public
class threadtest
}
同步的問題
當新增執行緒的push方法和取執行緒的pop方法,不是原子操作時意思就是push方法執行一半,cpu切換給pop方法的執行緒執行,就會出現問題。比如說,當執行了container[top]=a;但是還沒執行top++;切換到取執行緒時,把原來棧頂的元素取出來了並且指標向下減,如果再返回新增執行緒,繼續執行top++;結果就是新新增的元素丟失了,原來棧頂的元素取了一次還在。所以pop方法和push方法要加鎖,作為原子操作。
多執行緒之經典生產者消費者問題
通過訊號量,wait,nofity,synchronized來解決生產者消費者問題。例項如下 package thread public class threadwaitandnotifytest class iphone catch interruptedexception e system.ou...
多執行緒 生產者消費者
這個就不多說了,直接上 include include using namespace std const unsigned short size of buffer 10 緩衝區長度 unsigned short productid 0 產品號 unsigned short consumeid 0...
多執行緒生產消費者模式
package net.jxatei.jsj.thread 消費者與生產者共同的資源 author 安 緹 吖 public class clerk catch interruptedexception e try catch interruptedexception e system.out.pr...