手書き生産者--消費者モデルの例
8775 ワード
同時プログラミングでは,比較的古典的なプログラミング例が生産者と消費者モデルである.次に、生産者と消費者とは何か、彼らの特徴と注意点を説明する例を示します.
1、まずデータオブジェクトを定義し、
2.Runnableインタフェースを実装する生産者を定義します.
ここでいくつかの注意点があります.1つは、共有バッファの選択であり、生産者-消費者モデルとして、共有バッファは必ずブロックする能力を備えなければなりません.だからここで選んだのはブロックキューです.もう1つは,同時プログラミングの場合,i++のようなid自己成長機能を使用する必要がある場合,Atomicパッケージの下の同時クラスを使用する必要がある.これらのクラスはCAS設計を採用しているため、同時問題は発生しません.
3.消費者
消費者は主にブロックキューからデータを取得し、キューに要素がない場合はCPUを解放し、待機します.(注意ここではpollではなくtakeを使用していますが、takeは要素がないときにCPUを解放し、pollはnullに直接戻る点が違います).
main関数:
1、まずデータオブジェクトを定義し、
public class Data {
private String id;
private String name;
public Data(String id,String name){
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Data [id=" + id + ", name=" + name + "]";
}
}
2.Runnableインタフェースを実装する生産者を定義します.
public class Provider implements Runnable{
//
private BlockingQueue queue;
// , ,
private volatile boolean isRunning = true;
//id
private static AtomicInteger count = new AtomicInteger();
//
private static Random r = new Random();
public Provider(BlockingQueue queue){
this.queue = queue;
}
@Override
public void run() {
while(isRunning){
// 0-1000
try {
Thread.sleep(r.nextInt(1000));
//
int id = count.incrementAndGet();
// getData()
Data data = new Data(Integer.toString(id)," "+id);
System.out.println(" :"+ Thread.currentThread().getName() + ", ,id :"+ id+ ", 。。。");
if(!this.queue.offer(data,2,TimeUnit.SECONDS)){
System.out.print(" ");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("aaa");
}
}
public void stop(){
this.isRunning = false;
}
}
ここでいくつかの注意点があります.1つは、共有バッファの選択であり、生産者-消費者モデルとして、共有バッファは必ずブロックする能力を備えなければなりません.だからここで選んだのはブロックキューです.もう1つは,同時プログラミングの場合,i++のようなid自己成長機能を使用する必要がある場合,Atomicパッケージの下の同時クラスを使用する必要がある.これらのクラスはCAS設計を採用しているため、同時問題は発生しません.
3.消費者
public class Consumer implements Runnable {
private BlockingQueue queue;
public Consumer(BlockingQueue queu){
this.queue = queu;
}
//
private static Random r = new Random();
@Override
public void run() {
while(true){
try{
//
Data data = this.queue.take();
// , 0-1000
Thread.sleep(r.nextInt(1000));
System.out.print(" "+Thread.currentThread().getName() +", , id "+data.getId());
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
消費者は主にブロックキューからデータを取得し、キューに要素がない場合はCPUを解放し、待機します.(注意ここではpollではなくtakeを使用していますが、takeは要素がないときにCPUを解放し、pollはnullに直接戻る点が違います).
main関数:
public class Main {
public static void main(String[] args){
//
BlockingQueue queue = new LinkedBlockingQueue(10);
//
Provider p1 = new Provider(queue);
Provider p2 = new Provider(queue);
Provider p3 = new Provider(queue);
Consumer c1 = new Consumer(queue);
Consumer c2 = new Consumer(queue);
Consumer c3 = new Consumer(queue);
// , , , , 60s。
ExecutorService cachepool = Executors.newCachedThreadPool();
cachepool.execute(p1);
cachepool.execute(p2);
cachepool.execute(p3);
cachepool.execute(c1);
cachepool.execute(c2);
cachepool.execute(c3);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
p1.stop();
p2.stop();
p3.stop();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}