單一生產(chǎn)者,消費(fèi)者問(wèn)題:
class Resource{
private String name;
private int count=1;
private boolean flag=false;
public synchronized void set(String name){
if(flag)
try{
this.wait();
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生產(chǎn)者性湿。纬傲。。肤频。叹括。"+this.name);
flag=true;
notify();
}
public synchronized void out(){
if(!flag)
try{
this.wait();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消費(fèi)者。宵荒。汁雷。"+this.name);
flag=false;
notify();
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class XiaoFei {
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t1=new Thread(pro);
Thread t2=new Thread(con);
t1.start();
t2.start();
}
}
運(yùn)行:多生產(chǎn)多消費(fèi)問(wèn)題:
class Resource{
private String name;
private int count=1;
private boolean flag=false;
public synchronized void set(String name){
if(flag)
try{
this.wait();
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生產(chǎn)者。报咳。侠讯。。暑刃。"+this.name);
flag=true;
notify();
}
public synchronized void out(){
if(!flag)
try{
this.wait();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消費(fèi)者厢漩。。岩臣。"+this.name);
flag=false;
notify();
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class Many {
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t0=new Thread(pro);
Thread t1=new Thread(pro);
Thread t2=new Thread(con);
Thread t3=new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
如果直接創(chuàng)建多個(gè)線程溜嗜,會(huì)出現(xiàn)生產(chǎn)一次,卻消費(fèi)多次的沖突架谎,或者生產(chǎn)多個(gè)炸宵,卻消費(fèi)最近一個(gè)(即有生產(chǎn)的未被消費(fèi))的沖突。
這時(shí)可把判斷語(yǔ)句if換成while谷扣,但會(huì)出現(xiàn)死鎖現(xiàn)象土全。所以要在將notify改為notifyAll。即:
//多生產(chǎn)多消費(fèi)問(wèn)題
//if判斷標(biāo)記会涎,只有一次會(huì)導(dǎo)致不該執(zhí)行的線程運(yùn)行了涯曲。出現(xiàn)了數(shù)據(jù)錯(cuò)誤的情況
//while判斷標(biāo)記,解決了線程獲取執(zhí)行權(quán)后在塔,是否要運(yùn)行幻件!
//notify只能喚醒一個(gè)線程,如果本方喚醒了本方蛔溃,無(wú)意義绰沥。而且while判斷標(biāo)記+notify會(huì)導(dǎo)致死鎖篱蝇。
//notifyAll解決了,本方線程一定會(huì)喚醒對(duì)方線程徽曲。
class Resource{
private String name;
private int count=1;
private boolean flag=false;
public synchronized void set(String name){
while(flag)
try{
this.wait();
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生產(chǎn)者零截。。秃臣。涧衙。。"+this.name);
flag=true;
notifyAll();
}
public synchronized void out(){
while(!flag)
try{
this.wait();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消費(fèi)者奥此。弧哎。。"+this.name);
flag=false;
notifyAll();
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class YouHua {
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t0=new Thread(pro);
Thread t1=new Thread(pro);
Thread t2=new Thread(con);
Thread t3=new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
運(yùn)行:JDK1.5以后將同步和鎖封裝成了對(duì)象稚虎。并將操作鎖的隱式方式定義到了該對(duì)象中撤嫩,將隱式變成了顯示動(dòng)作。
Lock接口:出現(xiàn)替代了同步代碼塊或者同步函數(shù)蠢终。將同步的隱式鎖操作變成了顯式鎖操作序攘。同時(shí)更為靈活⊙胺鳎可以一個(gè)鎖上加上多組監(jiān)視器程奠。——lock();unclock();
Condition接口:出現(xiàn)替代了Object中的wait祭钉,notify瞄沙,notifyAll方法。將這些監(jiān)視器方法單獨(dú)進(jìn)行了封裝朴皆,變成Condition監(jiān)視器對(duì)象》捍猓可以任意鎖進(jìn)行組合遂铡。——await();singnal();singnalAll();
import java.util.concurrent.locks.*;
class Resource{
private String name;
private int count=1;
private boolean flag=false;
// 創(chuàng)建一個(gè)鎖對(duì)象晶姊。
Lock lock=new ReentrantLock();
//通過(guò)已有的鎖獲取該鎖上的監(jiān)視器對(duì)象扒接。
// Condition con=lock.newCondition();
//通過(guò)已有的鎖獲取兩組監(jiān)視器,一組監(jiān)視生產(chǎn)者们衙,一組監(jiān)視消費(fèi)者钾怔。
Condition producer_con = lock.newCondition();
Condition consumer_con = lock.newCondition();
public void set(String name){
lock.lock();
// try{lock.wait();}catch(InterruptedException e){}
try{
while(flag)
try{
producer_con.await();;
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生產(chǎn)者。蒙挑。宗侦。。忆蚀。"+this.name);
flag=true;
// con.signalAll();
consumer_con.signal();
}finally{
lock.unlock();
}
}
public void out(){
lock.lock();
// try{this.wait();}catch(InterruptedException e){}
try{
while(!flag)
try{
consumer_con.await();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消費(fèi)者矾利。姑裂。。"+this.name);
flag=false;
// con.signalAll();
producer_con.signal();
}finally{
lock.unlock();
}
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class lockandcondition {
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t0=new Thread(pro);
Thread t1=new Thread(pro);
Thread t2=new Thread(con);
Thread t3=new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
運(yùn)行效果同上男旗。
JDK1.5以后將同步和鎖封裝成了對(duì)象舶斧。
并將操作鎖的隱式方式定義到了
該對(duì)象中,將隱式變成了顯示動(dòng)作察皇。
Lock接口:出現(xiàn)替代了同步代碼塊或者同步函數(shù)茴厉。將同步的隱式鎖操作變成了顯式鎖操作。
同時(shí)更為靈活什荣》海可以一個(gè)鎖上加上多組監(jiān)視器。
lock();unclock();
Condition接口:出現(xiàn)替代了Object中的wait溃睹,notify而账,notifyAll方法。
將這些監(jiān)視器方法單獨(dú)進(jìn)行了封裝因篇,變成Condition監(jiān)視器對(duì)象泞辐。
可以任意鎖進(jìn)行組合。
await();singnal();singnalAll();
wait與sleep的區(qū)別:
1.wait可以指定時(shí)間也可以不指定竞滓。
sleep必須指定時(shí)間
2.在同步中時(shí)咐吼,對(duì)cpu的執(zhí)行權(quán)和鎖的處理不同。
wait:釋放執(zhí)行權(quán)商佑,釋放鎖锯茄。
sleep:釋放執(zhí)行權(quán),不釋放鎖茶没。
class Resource{
private String name;
private int count=1;
private boolean flag=false;
// 創(chuàng)建一個(gè)鎖對(duì)象肌幽。
Lock lock=new ReentrantLock();
//通過(guò)已有的鎖獲取該鎖上的監(jiān)視器對(duì)象。
// Condition con=lock.newCondition();
//通過(guò)已有的鎖獲取兩組監(jiān)視器抓半,一組監(jiān)視生產(chǎn)者喂急,一組監(jiān)視消費(fèi)者。
Condition producer_con = lock.newCondition();
Condition consumer_con = lock.newCondition();
public void set(String name){
lock.lock();
// try{lock.wait();}catch(InterruptedException e){}
try{
while(flag)
try{
producer_con.await();;
}catch(InterruptedException e){
}
this.name=name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生產(chǎn)者笛求。廊移。。探入。狡孔。"+this.name);
flag=true;
// con.signalAll();
consumer_con.signal();
}finally{
lock.unlock();
}
}
public void out(){
lock.lock();
// try{this.wait();}catch(InterruptedException e){}
try{
while(!flag)
try{
consumer_con.await();
}catch(InterruptedException e){
}
System.out.println(Thread.currentThread().getName()+"...消費(fèi)者。蜂嗽。苗膝。"+this.name);
flag=false;
// con.signalAll();
producer_con.signal();
}finally{
lock.unlock();
}
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.set("kaoya");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
public class lockandcondition {
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t0=new Thread(pro);
Thread t1=new Thread(pro);
Thread t2=new Thread(con);
Thread t3=new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
/*
停止線程:
1 stop方法。
2 run方法結(jié)束植旧。
怎么控制線程的任務(wù)結(jié)束呢荚醒?
任務(wù)中都會(huì)有循環(huán)結(jié)構(gòu)芋类,只要控制住循環(huán)就可以結(jié)束任務(wù)。
控制循環(huán)通常就用定義標(biāo)記來(lái)完成(變量flag)界阁。
但是如果線程處于凍結(jié)狀態(tài)侯繁,無(wú)法讀取標(biāo)記。如何結(jié)束呢泡躯?
可以使用interrupt()方法將線程從凍結(jié)狀態(tài)強(qiáng)制恢復(fù)到運(yùn)行狀態(tài)中來(lái)贮竟,讓線程具備cpu的執(zhí)行資格。
但是強(qiáng)制動(dòng)作會(huì)發(fā)生了InterruptedException较剃,記得要處理咕别。
*/
class StopThread implements Runnable{
private boolean flag=true;
public synchronized void run(){
while(flag){
try{
wait();
}catch(InterruptedException e){
System.out.println(Thread.currentThread().getName()+"....."+e);
flag=false;
}
System.out.println(Thread.currentThread().getName()+".....++++");
}
}
public void setFlag(){
flag=false;
}
}
public class StopThreadDemo {
public static void main(String[] args)
{
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.setDaemon(true);
t2.start();
int num = 1;
for(;;)
{
if(++num==50)
{
// st.setFlag();
t1.interrupt();
// t2.interrupt();
break;
}
System.out.println("main...."+num);
}
System.out.println("over");
}
}