简体   繁体   中英

Thread stops randomly without an error

So basically i'm learning about threads at the minute so i'm not 100% sure on them but i have created two producers and two consumers and they were working fine but I've changed something and now their not?

public class SingleBufferMonitor {

    private int buffer;
    private boolean full;

    public SingleBufferMonitor(){
        full = false;
    }

    public synchronized int get(){
        while(full == false) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
            notify();
            full = false;
            return buffer;

    }//get

    public synchronized void put(int value){
        while(full == true){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        buffer = value;
        full = true;
        notify();
    }//put
}

}

public class ConsumerThread extends Thread {

    private int aValue;
    private SingleBufferMonitor sharedBuffer;
    //private Random rand = new Random();

    public ConsumerThread(SingleBufferMonitor buffer, String name){
        super(name);
        sharedBuffer = buffer;
    }

    public void run(){
        String entrant;

        for(int count=1; count < 10; count++){
            try {
                Thread.sleep(1000);
                aValue = sharedBuffer.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if(count == 1){
                entrant = "person";
            }
            else{
                entrant = "people";
            }

            System.out.println(getName() + aValue + " " + entrant +" left");
        }
    }
}

}

public class ProducerThread extends Thread {

    private SingleBufferMonitor sharedBuffer;
    private Random rand = new Random();
    public long startTime, endTime, timeTaken, averageTime;


    public ProducerThread(SingleBufferMonitor buffer, String name){
        super(name);
        sharedBuffer = buffer;
    }

    public void run(){
        int tSleep = rand.nextInt(1000);
        String entrant;
        int count;

        for(count = 1; count < 10; count++){
            try {
                startTime = System.currentTimeMillis();
                Thread.sleep(tSleep);
                sharedBuffer.put(count);
                endTime = System.currentTimeMillis();
                timeTaken = endTime - startTime;
                averageTime = averageTime + timeTaken;

            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if(count == 1){
                entrant = "person";
            }
            else{
                entrant = "people";
            }

            System.out.println(getName() + count + " " + entrant +"  came in");
            System.out.println("Time taken for " + count + " " + entrant + " to get into the nightclub: " + timeTaken);
        }
        System.out.println("Average Time taken for " + count + " people to get into the nightclub via entrance 1: " + averageTime);
    }
}

}

class SingleBufferMonitorTest {

    public static void main(String[] args) throws Exception{
        SingleBufferMonitor box = new SingleBufferMonitor();

        ProducerThread producer1 = new ProducerThread(box, "Entrance 1: ");
        ProducerThread2 producer2 = new ProducerThread2(box, "Entrance 2: ");

        ConsumerThread consumer = new ConsumerThread(box, "Exit 1: ");
        ConsumerThread consumer2 = new ConsumerThread(box, "Exit 2: ");

        producer1.start();
        producer2.start();

        consumer.start();
        consumer2.start();
    }

}

Run program once output looks like;
Entrance 1: 1 person came in
Time taken for 1 person to get into the nightclub: 246
Entrance 1: 2 people came in
Exit 2: 1 person left
Time taken for 2 people to get into the nightclub: 754
Exit 2: 2 people left

Ran it a second time looks like;
Entrance 2: 1 person came in
Time taken for 1 person to get into the nightclub: 552
Entrance 1: 1 person came in
Exit 1: 1 person left
Exit 2: 1 person left
Time taken for 1 person to get into the nightclub: 1000
Entrance 2: 2 people came in
Time taken for 2 people to get into the nightclub: 552
Entrance 1: 2 people came in
Exit 2: 2 people left
Time taken for 2 people to get into the nightclub: 1001
Exit 2: 2 people left

etc.etc.

All I can see is that it appears to be the consumer thread causing the problem as it always ends on an "Exit". Also sometimes it makes its way throughout the entire program without stopping and works fine.

Guessing it has something to do with the threads interweaving wrong and both having to wait on nothing? (Just a guess)

PS Apologies about the mass of code but I genuinely have no idea whats causing this problem since i'm new to threads so I can't narrow it down.

Thanks in advance. :)

Your issue is that you're not waking up all the threads that are waiting on the implicit monitor in the SingleBufferMonitor object. There are 3 methods that are involved in using a monitor: wait, notify, and notifyAll . notifyAll() will wake up all current threads waiting on the monitor. The method you're calling will only wake up a single thread. Since you're only waking up one thread at a time one producer calling put() could wake up the other producer, which would see the buffer as full still and call wait() again. Both consumers are still waiting, and now both producers are waiting, and the program will not progress any further. If you change to using notifyAll() you will see the program finish.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM