Exception occurs during processing of wait and notify in java? : I was looking at a producer-consumer example with wait and notify, even though it works some times it gives exception. Not able to figure out where the problem is.

Exception in thread "Thread-5" java.util.NoSuchElementException
	at java.util.LinkedList.removeFirst(Unknown Source)
	at com.bhatsac.workshop.producerconsumer.ProdNConsumer.consumer(ProdNConsumer.java:55)
	at com.bhatsac.workshop.producerconsumer.ProdConsumerInvoker.lambda$5(ProdConsumerInvoker.java:35)
	at java.lang.Thread.run(Unknown Source)



Below is the code block


    import java.util.LinkedList;
    import java.util.concurrent.atomic.AtomicInteger;

    public class ProdNConsumer {

	LinkedList<Integer> list = new LinkedList<Integer>();
	private int LIMIT = 1;
	private volatile boolean shutdown = false;
	private AtomicInteger counter=new AtomicInteger(0);
	private Object lock=new Object();

	public void produce() {
		while (true) {
			synchronized(lock){
				System.out.println("In producer :)"+ list.size());
				if(this.list.size()==this.LIMIT){
					try {
						System.out.println("In waiting state producer");
						lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println("Produced by thread= "+ Thread.currentThread().getName());
				list.add(counter.getAndIncrement());
				System.out.println("Going to sleep for a while");
				lock.notifyAll();
			}
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public void consumer() {
		while (true) {
			synchronized(lock){
					System.out.println("In consumer :)");
					if(list.size()==0){
						try {
							System.out.println("In waiting state consumer");
							lock.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}	
					
					
					System.out.println("consumed by thread="+ Thread.currentThread().getName());
					list.removeFirst();
					
					lock.notifyAll();
				
							
			}
			
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
    }



    public class ProdConsumerInvoker {

	public static void main(String[] args) {
		
		ProdNConsumer pc= new ProdNConsumer();
		
		Thread tc1=new Thread(()->{
			
			pc.consumer();
		});
		
		new Thread(()->{
			
			pc.produce();
		}).start();
		new Thread(()->{
			
			pc.produce();
		}).start();
		
		
		Thread tp1=new Thread(()->{
			
			pc.produce();
		});
		
		new Thread(()->{
			
			pc.consumer();
		}).start();		
		new Thread(()->{
			
			pc.consumer();
		}).start();
		
		tp1.start();
		tc1.start();
			
	}
    }






