首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用通知唤醒RecursiveTask<V>?

如何用通知唤醒RecursiveTask<V>?
EN

Stack Overflow用户
提问于 2013-11-24 07:07:32
回答 2查看 217关注 0票数 0

当这些任务被ForkJoinPool方法搁置时,我怎么才能唤醒由ForkJoinPool调用的。下面是MainRecursionClass.resume方法的简单示例,它不正确(没有唤醒RecursiveTasks)。

代码语言:javascript
复制
public class Program {
   public static void main(String[] args) {
      Program p = new Program();
      final MainRecursionClass mrc = p.new MainRecursionClass();

      //Thread outputs integers to simulate work
      new Thread() {
         public void run() {
            mrc.doJob();
         }
      }.start();

      //Thread performs wait and notify on MainRecursionClass object
      p.new PauseResume(mrc).start();
   }

/**
 * 
 * This class performs suspend and resume operations to the MainRecursionClass class object
 *
 */
   private class PauseResume extends Thread {
      private MainRecursionClass rv;

      public PauseResume(MainRecursionClass rv) {
         this.rv = rv;
      }

      @Override
      public void run() {
         while(!isInterrupted()) {
            try {
               sleep(4000);

               rv.suspend();
               sleep(8000);

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

   private class MainRecursionClass {
      private boolean pause = false;
      private MyRecursive rv;

      public void doJob() {
         rv = new MyRecursive(0, 100000);
         ForkJoinPool pool = new ForkJoinPool();      
         pool.invoke(rv);
      }

      public void suspend() {
         pause = true;

         System.out.println("Suspended");
      }

      /**
       * This method is incorrect. It should wake up all MyRecursive instances to continue their work.
       */
      public synchronized void resume() {
         pause = false;
         notifyAll();

         System.out.println("Resumed");
      }

      private class MyRecursive extends RecursiveTask<Object> {
         private static final long serialVersionUID = 1L;
         private int start;
         private int length;
         private int threshold = 15;

         public MyRecursive(int start, int length) {
            super();
            this.start = start;
            this.length = length;
         }

         protected void computeDirectly() throws Exception {
            for (int index = start; index < start + length; index++) {
               //PAUSE
               synchronized (this) {
                  try {
                     while(pause) {
                        wait();
                     }
                  } catch (InterruptedException e) {
                     e.printStackTrace();
                  }
               }
               //PAUSE

               //some output to simulate work...
               System.out.println(index);

               Thread.sleep(1000);
            }
         }

         /**
          * Recursion
          */
         @Override
         protected Object compute() {
            if (length <= threshold) {
               try {
                  computeDirectly();
               } catch (Exception e) {
                  return e;
               }

               return null;
            }

            int split = length / 2;

            invokeAll(new MyRecursive(start, split),
                      new MyRecursive(start + split, length - split));

            return null;
         }
      }
   }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-24 15:19:02

最后,我找到了这个解决方案:我在MainRecursionClass中创建了MainRecursionClass对象,并在list中添加了递归创建的每个MyRecursive实例。类MyRecursive有新的方法:

代码语言:javascript
复制
public synchronized void resume() {
   notify();
}

当方法MainRecursionClass.resume()唤醒线程时,如下所示:

代码语言:javascript
复制
public void resume() {
   System.out.println("Resumed");

   pause = false;
   for(MyRecursive mr : list) {
      if(mr != null)
         mr.resume();
      }
   }
}
票数 0
EN

Stack Overflow用户

发布于 2013-11-24 13:19:51

在线程池上运行的任务中,不应使用等待/通知。如果您的池是有界的,那么它可能导致线程饥饿(死锁的一种形式)。如果没有限制,就会创建过多的线程并耗尽主内存。

相反,您应该将任务拆分为2(或更多),并根据其启动条件启动子任务。当您想要一个任务到wait(),然后重构它,使当前的子任务退出,下一个子任务准备运行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20172057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档