Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 并发求和列表,由另一个线程填充_Java_Multithreading_Concurrency - Fatal编程技术网

Java 并发求和列表,由另一个线程填充

Java 并发求和列表,由另一个线程填充,java,multithreading,concurrency,Java,Multithreading,Concurrency,有一个线程生成随机整数,并将它们放入列表中。还有两个线程同时使用列表中的项。这些线程需要汇总它们从列表中获取的项目。暂停这些线程,直到列表被填满。然后打印出两个线程的汇总结果 我认为这里应该使用wait()和notify()。然而,我不确定我是否正确理解这是如何工作的 此线程从列表中获取项目 @Override public void run() { try { while (list.size() > 0) { synchronized (list) {

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

我认为这里应该使用
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();
  }
}
@Override
public void run() {
    synchronized(list) {
        for (int i = 0; i < 10; i++) {
            list.add(random.nextInt());
        }
        list.notify();
    }
}
@覆盖
公开募捐{
试一试{
已同步(列表){
list.wait();
对于(int i=0;i<10;i++){
list.add(random.nextInt());
系统输出打印项次(“填写”);
}
list.notify();
}
}捕捉(中断异常e){
e、 printStackTrace();
}
}
但是,它们永远不会结束。

填充线程中的notify()调用只通知一个等待的线程。只有一个线程继续提取一个整数。然后它再次等待。没有任何东西触发通知,它将永远等待。只有当列表中没有任何内容时才需要等待

@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();
  }
}
@Override
public void run() {
    synchronized(list) {
        for (int i = 0; i < 10; i++) {
            list.add(random.nextInt());
        }
        list.notify();
    }
}
与其重新发明轮子,不如使用如下阻塞队列:

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 );
}
public Runnable createSum(最终阻塞队列,最终阻塞队列输出){
返回新的Runnable(){
公开募捐{
整数结果=0;
而(!queue.isEmpty()){
结果+=队列。take();
}
输出。输出(结果);
}
}
}
公开作废go(){
BlockingQueue输入=新建ArrayBlockingQueue();
BlockingQueue输出=新建ArrayBlockingQueue();
线程runner1=新线程(createSum(输入、输出));
线程runner2=新线程(createSum(输入、输出));
对于(int i=0;i<10;i++){
input.put(random.nextInt());
}
runner1.start();
runner2.start();
runner1.join();
runner2.join();
整数结果=0;
而(!output.isEmpty()){
结果+=输出。take();
}
系统输出打印项次(结果);
}

此解决方案仅在队列填满后才开始求和,但在您的解决方案中,它做的是相同的事情。

您的代码有许多问题:

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

这里有足够的混乱证据,我建议在开始编写代码之前,试着用一种更抽象的方式来思考这个问题。

我想我也误解了这个问题。这是正确的解决方案

这就填满了清单

@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();
  }
}
@Override
public void run() {
    synchronized(list) {
        for (int i = 0; i < 10; i++) {
            list.add(random.nextInt());
        }
        list.notify();
    }
}
基本上,他们只需要锁定列表本身

这将打印出最终解决方案:

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

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

对不起,问题不清楚。请提供一个例子,说明应该做什么happen@gerrytan这实际上是一个(非常令人困惑的)课程任务。我想我一开始也误解了。请看我的答案。您只需通知()一次,就可以在每个整数上等待()。这几乎肯定会在第一个整数之后阻塞,但如果在线程启动之前触发notify(),则可能从一开始就阻塞。如果不允许使用更高级别的并发库,则这是您唯一的选择。或者,如果您正在构建更高级别的并发数据结构和算法,那么您必须使用这些原语来实现。所以它们肯定有实际用途。是的,我不允许使用高级库。我明白为什么它是实用的,就像你说的那样。但这取决于算法和数据结构。我的意思是,如果我正确理解并发性,那么在本例中,线程管理的成本要比使用列表的实际操作高得多。当然,如果实际操作慢一点,我想会更好。顺便说一句,你的回答很有启发性!