자바 소비자 생산자 문제
9070 단어 자바 병행 학습
소비자 유형:
import java.util.ArrayList;
/**
* @author hetiantian
*
*/
public class Consumer implements Runnable {
private static ArrayList foods = new ArrayList<>(5);
public Consumer(ArrayList foods) {
this.foods = foods;
}
public static void eatFood() throws InterruptedException {
while (true) {
int last = foods.size() - 1;
Food f;
synchronized (foods) {
if (last < 0) {
foods.notify(); //
} else {
f = foods.get(last);
System.out.println(" :" + f);
foods.remove(last);
}
}
}
}
@Override
public void run() {
try {
eatFood();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
제품 종류:
import java.util.ArrayList;
/**
* @author hetiantian
*
*/
public class Producer implements Runnable {
// ,
private static ArrayList foods = new ArrayList<>(5);
static int id; //
public Producer(ArrayList foods) {
this.foods = foods;
}
//
public static void productFood() throws InterruptedException {
while (true) {
Food f = new Food(id++);
synchronized (foods) {
if (foods.size() >= 5) {
f.wait(); // 6 ,
} else {
foods.add(f);
System.out.println(" :" + f);
}
}
}
}
@Override
public void run() {
try {
productFood();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
테스트 클래스:
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* @author hetiantian
*
*/
public class ProductAndConsumerTest {
private static ArrayList foods = new ArrayList<>(5);
public static void main(String[] args) throws InterruptedException {
Producer p = new Producer(foods);
Consumer c = new Consumer(foods);
ExecutorService es = Executors.newCachedThreadPool();
es.execute(p);
es.execute(c);
TimeUnit.SECONDS.sleep(7);
//
es.shutdownNow();
}
}
-2.BlockingQueue 를 사용 하여 생산자 소비 자 를 모 의 하 는데,여기 서 제 가 선택 한 것 은 Array BlockingQueue 입 니 다.
요리사 종류:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* @author hetiantain
*/
public class Chief implements Runnable {
private static BlockingQueue blockingQueue = new ArrayBlockingQueue<>(5);
static int id = 0;
public Chief(BlockingQueue blockingQueue) {
this.blockingQueue = blockingQueue;
}
public static void createFood() throws InterruptedException {
Food f = new Food(id++);
blockingQueue.put(f);
System.out.println(" : " + f);
}
@Override
public void run() {
while (true) {
try {
createFood();
} catch (InterruptedException e) {
break;
}
}
}
}
식객 류:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* @author hetiantian
*
*/
public class Diners implements Runnable {
private static BlockingQueue blockingQueue = new ArrayBlockingQueue<>(5);
public Diners(BlockingQueue blockingQueue) {
this.blockingQueue = blockingQueue;
}
public static void eatFood() throws InterruptedException {
Food f = blockingQueue.take();
System.out.println(" " + f);
}
@Override
public void run() {
while (true) {
try {
eatFood();
} catch (InterruptedException e) {
break;
}
}
}
}
차단 대기 열 을 사용 하 는 것 은 인위적인 유지 가 필요 없 이 사용 하기에 매우 편리 하 다.
3-Condition 의 wait()와 signal()을 사용 하여 생산자 소비자 문 제 를 모 의 한다.
생산자:
import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* @author hetiantian
* (arrayList) , 5
*/
public class Producer implements Runnable {
private ArrayList arrayList;
private static int id; // id
Lock lock;
Condition notFull;
Condition notEmpty;
public Producer(ArrayList arrayList, Lock lock, Condition notFull, Condition notEmpty) {
this.arrayList = arrayList;
this.lock = lock;
this.notFull = notFull;
this.notEmpty = notEmpty;
}
@Override
public void run() {
//
lock.lock();
try {
while (true) {
Food f = new Food(++id);
System.out.println(" " + f);
arrayList.add(f);
notEmpty.signal();
if (arrayList.size() == 5) { // 5
System.out.println(" , , ");
notFull.await(); //
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
소비자:
import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* @author hetiantian
* ,
*/
public class Consumer implements Runnable {
private ArrayList arrayList;
Lock lock;
Condition notFull;
Condition notEmpty;
public Consumer(ArrayList arrayList, Lock lock, Condition notFull, Condition notEmpty) {
this.arrayList = arrayList;
this.lock = lock;
this.notFull = notFull;
this.notEmpty = notEmpty;
}
@Override
public void run() {
lock.lock();
try {
while (true) {
int last = arrayList.size() - 1;
Food food = arrayList.get(last);
System.out.println(" " + food);
arrayList.remove(food);
notFull.signal();
if (arrayList.size() == 0) { // ,
System.out.println(" , , ");
notEmpty.await();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); //
}
}
}
테스트 클래스:
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author hetiantian
*
*/
public class ConsumerAndProducerTest {
public static void main(String[] args) throws InterruptedException {
ExecutorService es = Executors.newCachedThreadPool();
ArrayList arrayList = new ArrayList<>(5);
Lock lock = new ReentrantLock();
Condition notFull = lock.newCondition();
Condition notEmpty = lock.newCondition();
Producer p = new Producer(arrayList, lock, notFull,notEmpty);
Consumer c = new Consumer(arrayList, lock, notFull,notEmpty);
es.execute(p);
Thread.sleep(1000); // 1
es.execute(c);
Thread.sleep(1000); // 1
es.shutdownNow(); //
}
}
Condition 을 사용 하 는 것 은 wait()를 사용 하 는 것 과 notify()를 사용 하 는 것 과 비슷 합 니 다.먼저 자 물 쇠 를 얻 은 다음 에 인위적인 대기 와 동기 화 를 실현 해 야 합 니 다.
소결:BlockingQueue(차단 대기 열)를 사용 하여 소비자 생산자 문 제 를 모 의 하 는 것 이 더욱 편리 합 니 다.차단 대기 열 을 사용 하지 않 을 때 동기 화 전략 과 스 레 드 간 깨 우기 전략 을 추가 로 실현 해 야 합 니 다.차단 대기 열 을 사용 할 때 대기 열 이 비어 있 을 때 소비자 스 레 드 가 막 히 고 대기 열 이 비어 있 지 않 을 때 자동 으로 깨 어 나 며 대기 열 이 가득 찼 을 때 생산자 스 레 드 가 막 히 고 대기 열 이 불만 일 때 자동 으로 깨 어 납 니 다.
주:왜 이상 한 코드 블록 에 break 를 사용 합 니까?es.shutdown Now()바 텀 을 호출 하 는 것 은 interupt()방법 으로 작업 을 끝 냅 니 다.break 를 호출 하지 않 으 면 계속 실 행 됩 니 다.interupt()는 스 레 드 가 중단 되 어야 한다 고 만 알려 주 고 적당 한 시간 에 중단 되 었 습 니 다.(현재 자신의 이해,이후 에 더 많은 보충 과 수정 을 풀 었 습 니 다)