Java等待/ notifyAll

时间:2013-12-06 20:03:51

标签: java multithreading stack

一个简单的线程程序,其中一个写入器放入堆栈,一个读取器从堆栈中弹出。

java.util.Stack;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class MailBox
{
   Stack<Integer> stack;

   static int num;

   public MailBox()
   {
       stack = new Stack<Integer>();

       num = 1;
   }
}

class Reader implements Runnable
{

   MailBox box;

   public Reader(MailBox box)
   {
       this.box = box;
   }

   public void run()
   {
       Thread.currentThread().setName("Reader " + MailBox.num++);

       for(int i = 0; i < 5; ++i)
       {
           synchronized (box)
           {
               try {

                   box.wait();

                   if(!box.stack.empty() && !box.stack.isEmpty())
                   {
                       int data = box.stack.pop();

  System.out.println(Thread.currentThread().getName() + " popped " + box.stack.pop());
                   }
                   else
                   {
                       System.out.println("Empty");
                   } 

               } catch (InterruptedException e) {
                   // TODO Auto-generated catch block
                   e.printStackTrace();
               }
           }

           try {
               Thread.currentThread();
               Thread.sleep(3000);
           } catch (InterruptedException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
           }
       }

   }
}

class Writer implements Runnable
{   
    MailBox box;

   public Writer(MailBox box)
   {
       this.box = box;
   }

   public void run()
   {
       int min = 1;
       int max = 3;

       Thread.currentThread().setName("Writer " + MailBox.num++);

       for(int i = 0; i < 5; ++i)
       {
           synchronized(box)
           {
               int data = (int)Math.random() * max + min;

               box.stack.push(data);

               System.out.println(Thread.currentThread().getName() + " pushed " + data);

               box.notifyAll();
           }

           try {
               Thread.sleep(3000);
           } catch (InterruptedException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
           }

        }

    }
}

public class Review 
{

   public static void main(String args[])
   {
       MailBox box = new MailBox();

       Writer writer = new Writer(box);

       Writer apprentice = new Writer(box);

       Writer publisher = new Writer(box);

       Reader reader = new Reader(box);

       Reader busy_reader = new Reader(box);

       Reader slow_reader = new Reader(box);

       Reader fast_reader = new Reader(box);

       Reader ugly_reader = new Reader(box);

       ExecutorService executor = Executors.newCachedThreadPool();

       executor.execute(writer);

       executor.execute(apprentice);

       executor.execute(publisher);

       executor.execute(reader);

       executor.execute(busy_reader);

       executor.execute(slow_reader);

       executor.execute(fast_reader);

       executor.execute(ugly_reader);

       executor.shutdown();

   }

}

程序似乎工作正常,但读者偶尔会弹出一个生成StackEmptyExceptions的空堆栈。

我有针对此的保护,为什么会产生这些例外?

1 个答案:

答案 0 :(得分:1)

您正在弹出对象两次:

int data = box.stack.pop();
System.out.println(Thread.currentThread().getName() + " popped " + box.stack.pop());

正如您在documentation of stack中看到的,pop获取并删除数据。