title: WorkStealingPool exits unexpectedly
body: <p>I submitted some Runnables to an ExecutorService. Inside these Runnables, wait() and notify() are called. The code works with newFixedThreadPool as the ExecutorService. With newWorkStealingPool, the process exits unexpectedly without any error message. </p>
  
  <pre><code>import java.net.URL;
  import java.io.BufferedReader;
  import java.io.InputStreamReader;
  import java.io.IOException;
  
  // For regular expressions
  import java.util.regex.Matcher;
  import java.util.regex.MatchResult;
  import java.util.regex.Pattern;
  
  import java.util.*;
  import java.util.concurrent.*;
  
  public class TestPipeline {
    public static void main(String[] args) {
      runAsThreads();
    }
  
    private static void runAsThreads() {
      final BlockingQueue&lt;String&gt; urls = new OneItemQueue&lt;String&gt;();
      final BlockingQueue&lt;Webpage&gt; pages = new OneItemQueue&lt;Webpage&gt;();
      final BlockingQueue&lt;Link&gt; refPairs = new OneItemQueue&lt;Link&gt;();
      final BlockingQueue&lt;Link&gt; uniqRefPairs = new OneItemQueue&lt;Link&gt;();
  
      final ExecutorService executor = Executors.newWorkStealingPool(6);
  //  final ExecutorService executor = Executors.newFixedThreadPool(6);
  
      executor.submit(new UrlProducer(urls));
      executor.submit(new PageGetter(urls, pages));
      executor.submit(new LinkScanner(pages,refPairs));
      executor.submit(new Uniquifier&lt;Link&gt;(refPairs,uniqRefPairs));
      executor.submit(new LinkPrinter(uniqRefPairs));
    }
  }
  
  class UrlProducer implements Runnable {
    private final BlockingQueue&lt;String&gt; output;
  
    public UrlProducer(BlockingQueue&lt;String&gt; output) {
      this.output = output;
    }
  
    public void run() {
      System.out.println("in producer"); 
      for (int i=0; i&lt;urls.length; i++)
        output.put(urls[i]);
    }
  
    private static final String[] urls = 
    { "http://www.itu.dk", "http://www.di.ku.dk", "http://www.miele.de",
      "http://www.microsoft.com", "http://www.cnn.com", "http://www.dr.dk",
      "http://www.vg.no", "http://www.tv2.dk", "http://www.google.com",
      "http://www.ing.dk", "http://www.dtu.dk", "http://www.bbc.co.uk"
    };
  }
  
  class PageGetter implements Runnable {
    private final BlockingQueue&lt;String&gt; input;
    private final BlockingQueue&lt;Webpage&gt; output;
  
    public PageGetter(BlockingQueue&lt;String&gt; input, BlockingQueue&lt;Webpage&gt; output) {
      this.input = input;
      this.output = output;
    }
  
    public void run() { 
      while (true) {
      System.out.println("in pagegetter"); 
        String url = input.take();
        //      System.out.println("PageGetter: " + url);
        try { 
          String contents = getPage(url, 200);
          output.put(new Webpage(url, contents));
        } catch (IOException exn) { System.out.println(exn); }
      }
    }
  
    public static String getPage(String url, int maxLines) throws IOException {
      // This will close the streams after use (JLS 8 para 14.20.3):
      try (BufferedReader in 
           = new BufferedReader(new InputStreamReader(new URL(url).openStream()))) {
        StringBuilder sb = new StringBuilder();
        for (int i=0; i&lt;maxLines; i++) {
          String inputLine = in.readLine();
          if (inputLine == null)
            break;
          else
          sb.append(inputLine).append("\n");
        }
        return sb.toString();
      }
    }
  }
  
  class Uniquifier&lt;T&gt; implements Runnable{
    private final Set&lt;T&gt; set = new HashSet&lt;T&gt;();
    private final BlockingQueue&lt;T&gt; input;
    private final BlockingQueue&lt;T&gt; output;
  
    public Uniquifier(BlockingQueue&lt;T&gt; input, BlockingQueue&lt;T&gt; output){
      this.input = input;
      this.output = output;
    }
  
  
    public void run(){
      while(true){
        System.out.println("in uniquifier");
        T item = input.take();
        if(!set.contains(item)){
          set.add(item);
          output.put(item);
        }
      }
    }
  
  }
  
  class LinkScanner implements Runnable {
    private final BlockingQueue&lt;Webpage&gt; input;
    private final BlockingQueue&lt;Link&gt; output;
  
    public LinkScanner(BlockingQueue&lt;Webpage&gt; input, 
                       BlockingQueue&lt;Link&gt; output) {
      this.input = input;
      this.output = output;
    }
  
    private final static Pattern urlPattern 
      = Pattern.compile("a href=\"(\\p{Graph}*)\"");
  
    public void run() { 
      while (true) {
        System.out.println("in link scanner"); 
        Webpage page = input.take();
        //      System.out.println("LinkScanner: " + page.url);
        // Extract links from the page's &lt;a href="..."&gt; anchors
        Matcher urlMatcher = urlPattern.matcher(page.contents);
        while (urlMatcher.find()) {
          String link = urlMatcher.group(1);
          output.put(new Link(page.url, link));
        }
      }
    }
  }
  
  class LinkPrinter implements Runnable {
    private final BlockingQueue&lt;Link&gt; input;
  
    public LinkPrinter(BlockingQueue&lt;Link&gt; input) {
      this.input = input;
    }
  
    public void run() { 
      while (true) {
        System.out.println("in link printer"); 
        Link link = input.take();
        //      System.out.println("LinkPrinter: " + link.from);
        System.out.printf("%s links to %s%n", link.from, link.to);
      }
    }
  }
  
  
  class Webpage {
    public final String url, contents;
    public Webpage(String url, String contents) {
      this.url = url;
      this.contents = contents;
    }
  }
  
  class Link {
    public final String from, to;
    public Link(String from, String to) {
      this.from = from;
      this.to = to;
    }
  
    // Override hashCode and equals so can be used in HashSet&lt;Link&gt;
  
    public int hashCode() {
      return (from == null ? 0 : from.hashCode()) * 37
           + (to == null ? 0 : to.hashCode());
    }
  
    public boolean equals(Object obj) {
      Link that = obj instanceof Link ? (Link)obj : null;
      return that != null 
        &amp;&amp; (from == null ? that.from == null : from.equals(that.from))
        &amp;&amp; (to == null ? that.to == null : to.equals(that.to));
    }
  }
  
  // Different from java.util.concurrent.BlockingQueue: Allows null
  // items, and methods do not throw InterruptedException.
  
  interface BlockingQueue&lt;T&gt; {
    void put(T item);
    T take();
  }
  
  class OneItemQueue&lt;T&gt; implements BlockingQueue&lt;T&gt; {
    private T item;
    private boolean full = false;
  
    public void put(T item) {
      synchronized (this) {
        while (full) {
          try { this.wait(); } 
          catch (InterruptedException exn) { }
        }
        full = true;
        this.item = item;
        this.notifyAll();
      }
    }
  
    public T take() {
      synchronized (this) {
        while (!full) {
          try { this.wait(); } 
          catch (InterruptedException exn) { }
        }
        full = false;
        this.notifyAll();
        return item;
      }
    }
  }
  </code></pre>