具有并发性的汇总列表,由另一个线程填充

时间:2014-03-09 22:05:49

标签: java multithreading concurrency

  

有一个产生随机整数的线程,并将它们放入一个列表中。还有两个线程同时使用列表中的项目。这些线程需要总结他们从列表中获取的项目。暂停这些线程,直到填充列表。然后打印出两个线程的总和结果。

我认为,wait()notify()应该在这里使用。但是,我不确定我是否正确理解它是如何工作的。

此线程从列表中抓取项目

@Override
public void run() {
  try
  {
    while (list.size() > 0) {
      synchronized (list) {
        list.wait();
        result += (Integer) list.remove(0);
      }
    }

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

这就是填写清单的内容。

@Override
public void run() {
  try {
    synchronized (list) {
      list.wait();
      for (int i = 0; i < 10; i++) {
        list.add(random.nextInt());
        System.out.println("fill");
      }
      list.notify();
    }
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
}

然而,他们永远不会完成。

3 个答案:

答案 0 :(得分:1)

您的代码存在许多问题:

  • 您声称有两个线程从列表中读取,但您只显示一个。
  • 您在访问列表之前将其锁定在第一个代码块中。您需要将while(list)语句放在while循环周围。
  • 填写列表的代码等待没有任何要通知的内容。
  • 如果您的列表中的抓取项目首先运行,则列表将为空,因此它不会执行任何操作。那可能不是你想要的。

有证据表明存在足够的混淆,我建议在开始编写代码之前尝试以更抽象的方式思考这个问题。

答案 1 :(得分:1)

我觉得我太误解了这个问题。这是正确的解决方案。

填写清单。

@Override
public void run() {
    synchronized(list) {
        for (int i = 0; i < 10; i++) {
            list.add(random.nextInt());
        }
        list.notify();
    }
}

这是项目的总和。

@Override
public void run() {
    synchronized(list) {
        while (list.size() > 0) {
            result += (Integer) list.remove(0);
        }
        list.notify();
    }
}

所以他们只需要自己锁定列表。

这样,打印出最终解决方案:

    try {
        sum1.join();
        sum2.join();
        System.out.println(sum1.getResult() + sum2.getResult());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

无论如何,我不认为这样实现的并发性没有任何实际用途 - 这只是一个课程任务。

答案 2 :(得分:0)

填充线程中的notify()调用仅通知其中一个等待线程。只有一个线程继续拉一个整数。然后它再次等待。没有任何解雇通知,它会永远等待。它只需等待列表中没有任何内容。

使用像这样的BlockingQueue而不是重新发明轮子:

public Runnable createSum( final BlockingQueue<Integer> queue, final BlockingQueue<Integer> output ) {
   return new Runnable() {
      public void run() {
          Integer result = 0;
          while( !queue.isEmpty() ) {
              result += queue.take();
          }
          output.put( result );
      }
   }
}

public void go() {
    BlockingQueue<Integer> input = new ArrayBlockingQueue<Integer>();
    BlockingQueue<Integer> output = new ArrayBlockingQueue<Integer>();
    Thread runner1 = new Thread( createSum( input, output ) );
    Thread runner2 = new Thread( createSum( input, output ) );
    for( int i = 0; i < 10; i++ ) {
        input.put( random.nextInt() );
    }

    runner1.start();
    runner2.start();

    runner1.join();
    runner2.join();

    Integer result = 0;
    while( !output.isEmpty() ) {
        result += output.take();
    }
    System.out.println( result );
}

此解决方案仅在队列填满后才开始对事物进行求和,但在您的解决方案中它正在做同样的事情。