Java WorksteachingPool意外退出
我向Executor服务提交了一些Runnable。在这些可运行程序中,调用wait()和notify()。该代码将newFixedThreadPool用作ExecutorService。使用newWorkStealingPool,进程意外退出,没有任何错误消息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; //
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方法,然后主线程退出。你看到你的其他系统输出了吗?你很正确。在最后一次提交后放置终止解决了问题。酷,我将把它作为答案。