分析:
1.在庫存爲滿時,生產者纔可以生產,同理有庫存時消費者纔可以消費,否則就等待。
2.當消費者消費完,活着生產者生產完 應該去通知對方,並釋放對象鎖
3.對象的wait方法,wait方法的作用是釋放當前線程的所獲得的鎖,
4.notifyAll() 方法, 通知(喚醒)該對象上其他等待線程,使得其繼續執行。
主類:ThreadMain
package com.wh.blog;
public class ThreadMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
//實例化庫存類,並初始化庫存爲50
Stock stock=new Stock(50);
for(int i=0;i<2;i++){
//設置三個消費者的子線程,消費水平分別爲:30 ,10,40 並調用啓動線程
new Thread(new Consumer(stock,30)).start();
new Thread(new Consumer(stock,10)).start();
new Thread(new Consumer(stock,40)).start();
//設置三個生產者的子線程,生產量分別爲:10 ,20,30 並調用啓動線程
new Thread(new Producer(stock,10)).start();
new Thread(new Producer(stock,20)).start();
new Thread(new Producer(stock,30)).start();
}
}
}
庫存類:Stock
package com.wh.blog;
public class Stock {
static int MAX=100;//最大庫存量
int current;//當前庫存
public Stock(int current){
this.current=current;
}
public synchronized void producer(int num){
//測試是否需要生產
while(num+current>MAX){
System.out.println("超出了剩餘的庫存量,當前生產了:"+num+" 個蘋果,不能存放在倉庫!");
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//while
current=current+num;
System.out.println("已生產了: "+num+"個蘋果 , 當前庫存爲:"+current);
//喚醒在此對象監視器上等待的所有線程
notifyAll();
}
public synchronized void consumer(int num){
//測試是否需要消費
while(num>current){
System.out.println("消費超出了當前的庫存量,當前消費的 "+num+"個蘋果失效");
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//while
current=current-num;
System.out.println("已吃掉了: "+num+"個蘋果, 當前庫存爲:"+current);
//喚醒在此對象監視器上等待的所有線程
notifyAll();
}
}
生產者類:Producer
package com.wh.blog;
public class Producer implements Runnable{
Stock stock;
int num;
public Producer(Stock stock,int num){
this.stock=stock;
this.num=num;
}
//實現了Runaable接口,並重寫run方法
@Override
public void run() {
// TODO Auto-generated method stub
//生產指定數量的產品
stock.producer(num);
}
}
消費者類:
package com.wh.blog;
public class Consumer implements Runnable{
Stock stock;
int num;
public Consumer(Stock stock,int num){
this.stock=stock;
this.num=num;
}
@Override
public void run() {
// TODO Auto-generated method stub
//消費指定數量的產品
stock.consumer(num);
}
}
線程基礎知識點
package study.theard;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MyThrard {
public static void main(String[] args) {
// TODO Auto-generated method stub
// Thread bb=new Thread(able);
// bb.setDaemon(true);
//daemon 所謂後臺線程是指程序運行的時候在後臺提供一種通用的服務 當所有非後臺線程結束時 才結束
// isDaemon()方法來確認線程是否爲後臺線程
// sleep休眠 將任務執行中止給定的時間
// 老版 的 Thread.sleep(100)
// try {
// TimeUnit.MILLISECONDS.sleep(100);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// getPriority() setPriority() 在任何時候獲取和設置線程優先級
// bb.yield();讓步 但並不保證 會被採納
// CachedThreadPool會將初始化的線程緩存起來 會終止從緩存中移除已有很久沒用的線程。
// ExecutorService 具有服務生命週期的Executor 創建 關閉
ExecutorService exec=Executors.newCachedThreadPool();
for(int i=0;i<3;i++){
exec.execute(able);
}
exec.shutdown();
// ExecutorService execb=Executors.newFixedThreadPool(5);
//固定的 省了創建是的開銷
}
static Runnable able=new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<80;i++)
System.out.println("k= "+i);
}
};
static Callable call=new Callable(){
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
return "???";
}
};
}