具有Java中的重入锁定和条件的生产者消费者方案

时间:2013-08-05 18:40:37

标签: java concurrency synchronization locking

我使用Reentrant Lock和condition编写了一个Producer Consumer程序。它工作正常,但我不确定实现是否正确。而且它似乎不是最佳的。有人可以验证这是否是一个正确的实现,而且你能告诉我,如何优化它,如 - 在真正需要的地方锁定

public class TestRL {

static class Observed {
    boolean filled = false;

    public void setFilled(boolean filled) {
        this.filled = filled;
    }

    public boolean getFilled() {
        return filled;
    }
}

static Observed observed = new Observed();

static class Consumer implements Runnable {
    Observed observed;
    ReentrantLock lock;
    Condition condition;

    Consumer(Observed observed, ReentrantLock lock, Condition condition) {
        this.observed = observed;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        try {
            for (int i = 0; i < 20; i++) {
                if (observed.getFilled() == false) {
                    try {
                        System.out.println("consumer waiting");
                        condition.await();
                        System.out.println("consumed");

                        Thread.sleep(400 + 1000 * i % 2);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    observed.setFilled(false);
                    condition.signalAll();
                }else{
                    observed.setFilled(false);
                    condition.signalAll();
                }
            }
        } finally {
            lock.unlock();
        }

    }
}

static class Producer implements Runnable {
    Observed observed;
    ReentrantLock lock;
    Condition condition;

    Producer(Observed observed, ReentrantLock lock, Condition condition) {
        this.observed = observed;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        try {
            for (int i = 0; i < 20; i++) {
                if (observed.getFilled() == true) {
                    try {
                        System.out.println("producer waiting");
                        condition.await();
                        System.out.println("produced");
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    observed.setFilled(true);
                    condition.signalAll();
                }else{
                    observed.setFilled(true);
                    condition.signalAll();
                }
            }
        } finally {
            lock.unlock();
        }

    }
}

/**
 * @param args
 */
public static void main(String[] args) {
    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    Producer producer = new Producer(observed, lock, condition);
    Consumer consumer = new Consumer(observed, lock, condition);
    Thread t1 = new Thread(producer);
    Thread t2 = new Thread(consumer);
    t1.start();
    t2.start();

}

}

4 个答案:

答案 0 :(得分:3)

以下是另一个使用ReentrantLock&amp; amp; amp;条件。以防万一有人想要。

package reentrant_prodcons;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;


public class Reentrant_ProdCons {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here

        Queue<Integer> queue=new LinkedList<Integer>();
        ReentrantLock lock=new ReentrantLock();
        Condition con=lock.newCondition();
        final int size = 5;

        new Producer(lock, con, queue, size).start();
        new Consumer(lock, con, queue).start();

    }

}


class Producer extends Thread{

    ReentrantLock  lock;
    Condition con;
    Queue<Integer> queue;
    int size;

    public Producer(ReentrantLock lock, Condition con, Queue<Integer> queue, int size) {
        this.lock = lock;
        this.con = con;
        this.queue = queue;
        this.size=size;
    }


    public void run(){
        for(int i=0;i<10;i++){
            lock.lock();
            while(queue.size()==size){
                try {
                    con.await();
                } catch (InterruptedException ex) {
                    Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            queue.add(i);
            System.out.println("Produced : "+i);
            con.signal();
            lock.unlock();
        }
    }

}

class Consumer extends Thread{


    ReentrantLock lock;
    Condition con;
    Queue<Integer> queue;


    public Consumer(ReentrantLock lock, Condition con, Queue<Integer> queue) {
        this.lock = lock;
        this.con = con;
        this.queue = queue;
    }

    public void run(){
        for(int i=0;i<10;i++){
           lock.lock();
           while(queue.size()<1){
               try {
                   con.await();
               } catch (InterruptedException ex) {
                   Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
               }
           }
            System.out.println("Consumed : "+queue.remove());
            con.signal();
            lock.unlock();
        }
    }
}

答案 1 :(得分:2)

希望有帮助。您可以通过更改使用者/生产者的等待时间来轻松检查代码中的上溢/下溢情况。

    @Module
interface BaseFontFragmentModule {

    @ContributesAndroidInjector(modules = [])
    fun inject(): BaseFontFragment

}

@Module
interface BaseFontActivityModule{

    @ContributesAndroidInjector(modules = [
        BaseFontFragmentModule::class
    ])
    fun inject(): BaseFontActivity

}

答案 2 :(得分:0)

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.logging.Level;
    import java.util.logging.Logger;

    /*
     * To change this license header, choose License Headers in Project Properties.
     * To change this template file, choose Tools | Templates
     * and open the template in the editor.
     */
    /**
     *
     * @author sakshi
     */
    public class ReentrantLockDemo {

        static List<Integer> list = new ArrayList<Integer>();
        static ReentrantLock lock = new ReentrantLock();
        static Condition ProdCons = lock.newCondition();

      static class Producer extends Thread {

            List<Integer> list;
            Producer(List<Integer> list) {
                this.list = list;

            }

            public void run() {

                for (int i = 0; i < 10; i++) {
                    lock.lock();

                    if (list.size() >=1) {
                        try {
                            ProdCons.await();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(ReentrantLockDemo.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }

                    list.add(i);
                    System.out.println("produce="+i);
                     ProdCons.signalAll();

                      lock.unlock(); 

                }

            }

        }

        static class Consumer extends Thread {

            List<Integer> list;


            Consumer(List<Integer> list) {
                this.list = list;

            }

            @Override
            public void run() {

                for (int i = 0; i < 10; i++) {
                      lock.lock();
                    while (list.isEmpty()) {
                        try {
                            ProdCons.await();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(ReentrantLockDemo.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }

                        System.out.println("consume=" +list.remove(0));
                        ProdCons.signalAll();

                        lock.unlock();
                    }

            }
        }


        public static void main(String[] args) {
            Producer produce = new Producer(list);
            Consumer consume = new Consumer(list);
            produce.start();
            consume.start();
        }
    }


output:
produce=0
consume=0
produce=1
consume=1
produce=2
consume=2
produce=3
consume=3
produce=4
consume=4
produce=5
consume=5
produce=6
consume=6
produce=7
consume=7
produce=8
consume=8
produce=9
consume=9

答案 3 :(得分:0)

docker commit 1e7 apache/nifi:latest2