자바 소비자 생산자 문제

9070 단어 자바 병행 학습
-1.wait()와 notify()를 사용 하여 시 뮬 레이 션
소비자 유형:
    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()는 스 레 드 가 중단 되 어야 한다 고 만 알려 주 고 적당 한 시간 에 중단 되 었 습 니 다.(현재 자신의 이해,이후 에 더 많은 보충 과 수정 을 풀 었 습 니 다)

좋은 웹페이지 즐겨찾기