Java WorksteachingPool意外退出

Java WorksteachingPool意外退出,java,concurrency,Java,Concurrency,我向Executor服务提交了一些Runnable。在这些可运行程序中,调用wait()和notify()。该代码将newFixedThreadPool用作ExecutorService。使用newWorkStealingPool,进程意外退出,没有任何错误消息 import java.net.URL; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; //

我向Executor服务提交了一些Runnable。在这些可运行程序中,调用wait()和notify()。该代码将newFixedThreadPool用作ExecutorService。使用newWorkStealingPool,进程意外退出,没有任何错误消息

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<String> urls = new OneItemQueue<String>();
    final BlockingQueue<Webpage> pages = new OneItemQueue<Webpage>();
    final BlockingQueue<Link> refPairs = new OneItemQueue<Link>();
    final BlockingQueue<Link> uniqRefPairs = new OneItemQueue<Link>();

    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<Link>(refPairs,uniqRefPairs));
    executor.submit(new LinkPrinter(uniqRefPairs));
  }
}

class UrlProducer implements Runnable {
  private final BlockingQueue<String> output;

  public UrlProducer(BlockingQueue<String> output) {
    this.output = output;
  }

  public void run() {
    System.out.println("in producer"); 
    for (int i=0; i<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<String> input;
  private final BlockingQueue<Webpage> output;

  public PageGetter(BlockingQueue<String> input, BlockingQueue<Webpage> 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<maxLines; i++) {
        String inputLine = in.readLine();
        if (inputLine == null)
          break;
        else
        sb.append(inputLine).append("\n");
      }
      return sb.toString();
    }
  }
}

class Uniquifier<T> implements Runnable{
  private final Set<T> set = new HashSet<T>();
  private final BlockingQueue<T> input;
  private final BlockingQueue<T> output;

  public Uniquifier(BlockingQueue<T> input, BlockingQueue<T> 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<Webpage> input;
  private final BlockingQueue<Link> output;

  public LinkScanner(BlockingQueue<Webpage> input, 
                     BlockingQueue<Link> 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 <a href="..."> 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<Link> input;

  public LinkPrinter(BlockingQueue<Link> 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<Link>

  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 
      && (from == null ? that.from == null : from.equals(that.from))
      && (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<T> {
  void put(T item);
  T take();
}

class OneItemQueue<T> implements BlockingQueue<T> {
  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;
    }
  }
}
import java.net.URL;
导入java.io.BufferedReader;
导入java.io.InputStreamReader;
导入java.io.IOException;
//对于正则表达式
导入java.util.regex.Matcher;
导入java.util.regex.MatchResult;
导入java.util.regex.Pattern;
导入java.util.*;
导入java.util.concurrent.*;
公共类测试管道{
公共静态void main(字符串[]args){
runashreads();
}
私有静态void runashtreads(){
final BlockingQueue url=new-OneItemQueue();
final BlockingQueue pages=new OneItemQueue();
final BlockingQueue refPairs=new OneItemQueue();
final BlockingQueue uniqRefPairs=new OneItemQueue();
最终执行者服务执行者=执行者。新工作教学池(6);
//final ExecutorService executor=Executors.newFixedThreadPool(6);
执行人提交(新UrlProducer(URL));
提交(新页面获取器(URL、页面));
提交(新链接扫描程序(页面、参考对));
执行人提交(新的合并人(参考对、参考对));
执行人提交(新链接打印机(uniqRefPairs));
}
}
类UrlProducer实现可运行{
私有最终阻塞队列输出;
公共UrlProducer(阻塞队列输出){
这个。输出=输出;
}
公开募捐{
System.out.println(“生产商内部”);

对于(int i=0;i因为池正在动态分配线程,所以在runAsThreads退出后没有线程处于活动状态,因为这是主线程的结束。需要至少有on thread在运行以保持应用程序处于活动状态。需要添加对awaitTermination的调用。固定池不需要这样做,因为它将始终具有活动线程,直到它如JavaDocs中所述被显式关闭。

尝试在上次提交后添加调试语句。我猜您会在程序退出之前看到它。我认为发生的情况与工作测试池可以调整线程数量的事实有关。当您到达t结尾时,可能没有他运行ashtreads方法,然后主线程退出。你看到你的其他系统输出了吗?你很正确。在最后一次提交后放置终止解决了问题。酷,我将把它作为答案。