Second thread doesn't start in producer consum

2019-08-29 08:14发布

问题:

I'm trying to implement Producer and Consumer problem by using semaphores in java. The issue is when I start two threads (Producer and Consumer) consumer doesn't start and producer blocks itself after buffer is full. I mean it looks like there is only one thread which works in synchronous manner. Thus, as I mentioned I use 3 semaphores which are empty, full, and mutex. Here is the simplest code;

Producer class;

import java.util.concurrent.Semaphore;

public class Producer implements Runnable {

    private Semaphore empty;
    private Semaphore full;
    private Semaphore mutex;

    public Producer(Semaphore empty, Semaphore full, Semaphore mutex) {

        this.empty = empty;
        this.full = full;
        this.mutex = mutex;
    }

    @Override
    public void run() {

        while (true) {

            try {
                empty.acquire();
                mutex.acquire();
                Thread.sleep(500);
                System.out.println("Producer producess an element");
                mutex.release();
                full.release();
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
        }
    }
}

Consumer class;

import java.util.concurrent.Semaphore;

public class Consumer implements Runnable {

    private Semaphore empty;
    private Semaphore full;
    private Semaphore mutex;

    public Consumer(Semaphore empty, Semaphore full, Semaphore mutex) {

        this.empty = empty;
        this.full = full;
        this.mutex = mutex;
    }

    @Override
    public void run() {

        while (true) {

            try {
                full.acquire();
                mutex.acquire();
                Thread.sleep(500);
                System.out.println("Consumer consumes an element");
                mutex.release();
                empty.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

ProducerConsumerExample class

import java.util.concurrent.Semaphore;

public class ProducerConsumerProblem {

    private Semaphore empty;
    private Semaphore full;
    private Semaphore mutex;

    public ProducerConsumerProblem(int empty, int full) {

        this.empty = new Semaphore(empty);
        this.full = new Semaphore(full);
        this.mutex = new Semaphore(1);

    }

    public void runProducerConsumerExample() {

        Producer producer = new Producer(empty, full, mutex);
        Consumer consumer = new Consumer(empty, full, mutex);

        Thread p = new Thread(producer);
        Thread c = new Thread(consumer);

        p.run();
        c.run();
    }
}

And finally test class

import org.junit.Before;
import org.junit.Test;

public class ProducerConsumerProblemTest {

    private ProducerConsumerProblem testClass;
    private static final int        EMPTY = 10;
    private static final int        FULL  = 0;

    @Before
    public void setUp() {

        testClass = new ProducerConsumerProblem(EMPTY, FULL);
    }

    @Test
    public void testName() {

        testClass.runProducerConsumerExample();
    }
}

Output:

Producer producess an element
Producer producess an element
Producer producess an element
Producer producess an element
Producer producess an element
Producer producess an element
Producer producess an element
Producer producess an element
Producer producess an element
Producer producess an element

After 10 items produced nothing happens and thread gets blocked.

回答1:

Don't use run(), use start()

    p.run();
    c.run();

should be

    p.start();
    c.start();

Calling run() doesn't generate a new thread of execution. It merely runs the functionality within the current thread of execution.

See this question/answer for more details.

Note also that I would shutdown the threads properly at the end of your test run (otherwise you'll build up multiple threads as you add/run tests). Interrupt your threads or set a volatile boolean indicating that your loops should complete.