java 中的执行程序终止递归如何?
How is an executor termination recursion in java?
这是一个程序,它使用递归读取以前格式的信息站点,executor.It 工作正常,我的问题是测试程序是否完成和成功通知。
public class NewClass {
static String levels[] = { "div.col-md-9 li a", "div#sidebar ul li a" };
static String links = "";
private void getRecursive(String href, int level, final ExecutorService executor) {
if (level > levels.length - 1) {
return;
}
Document doc;
try {
doc = Jsoup.connect(href).get();
Elements elements = doc.select(levels[level]);
final int flevel = ++level;
for (final Element element : elements) {
executor.execute(new Runnable() {
@Override
public void run() {
if (!element.attr("href").isEmpty()) {
links += element.attr("abs:href") + "\n";
System.out.println(links);
getRecursive(element.attr("abs:href"), flevel, executor);
}
}
});
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
如果levels.length = 1,规则执行器运行良好,但如果levels.length>1将出现错误:线程异常 "pool-1-thread-138" java.util.concurrent.RejectedExecutionException
public static void main(String[] args) {
try {
ExecutorService executor = Executors.newFixedThreadPool(5);
new NewClass().getRecursive("http://www.java2s.com/", 0, executor);
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
if (executor.isTerminated()) {
JOptionPane.showMessageDialog(null, "Success");
}
} catch (Exception ex) {
Logger.getLogger(NewClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
问题是您在调用 executor.shutdown()
之后调用 executor.execute
。 awaitTermination
方法仅等待调用 shutdown
之前提交的任务。
这就是发生这种情况的原因:
- 假设程序在线程
main
上启动。
executor.execute
的第一个电话是在 main
。
- 假设执行程序现在在
thread-pool-1
上运行,它还调用 executor.execute
。
- 但在执行这些新任务之前,我们跳回到
main
并调用 executor.shutdown
。
- 执行器可能会再次开始执行任务,这次可能是
thread-pool-2
,它会尝试调用 executor.execute
。但是,executor.shutdown()
已经被调用,因此抛出 java.util.concurrent.RejectedExecutionException
。
有几种方法可以解决这个问题:
- 在这种情况下使用执行器可能有点矫枉过正;只做单线程可能就足够了。
- 也许可以重构代码,以便最后的
executor.execute
可以调用 executor.shutdown
。但是,如果没有明确的最后调用,这将是不可能的。
如果您绝对需要在主线程之外执行此操作,您可以在其自己的线程中执行整个递归调用:
public static void main(String[] args) {
try {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() {
@Override
public void run() {
NewClass.getRecursive("http://www.java2s.com/", 0);
}
});
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
if (executor.isTerminated()) {
JOptionPane.showMessageDialog(null, "Success");
}
}
catch (Exception ex)
{
Logger.getLogger(NewClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
和
private static class NewClass {
static String levels[] = { "div.col-md-9 li a", "div#sidebar ul li a" };
static String links = "";
private static void getRecursive(String href, int level) {
if (level > levels.length - 1) {
return;
}
Document doc;
try {
doc = Jsoup.connect(href).get();
Elements elements = doc.select(levels[level]);
final int flevel = ++level;
for (final Element element : elements) {
if (!element.attr("href").isEmpty()) {
links += element.attr("abs:href") + "\n";
System.out.println(links);
getRecursive(element.attr("abs:href"), flevel);
}
}
}
catch (IOException e1) {
e1.printStackTrace();
}
}
}
您关闭ExecutorService
后无法提交任何新任务,递归似乎在您处理完所有级别后停止(之后您不提交任何新任务),您可以这样做:
if (level > levels.length - 1) {
executor.shutdown();
return;
}
这是一个程序,它使用递归读取以前格式的信息站点,executor.It 工作正常,我的问题是测试程序是否完成和成功通知。
public class NewClass {
static String levels[] = { "div.col-md-9 li a", "div#sidebar ul li a" };
static String links = "";
private void getRecursive(String href, int level, final ExecutorService executor) {
if (level > levels.length - 1) {
return;
}
Document doc;
try {
doc = Jsoup.connect(href).get();
Elements elements = doc.select(levels[level]);
final int flevel = ++level;
for (final Element element : elements) {
executor.execute(new Runnable() {
@Override
public void run() {
if (!element.attr("href").isEmpty()) {
links += element.attr("abs:href") + "\n";
System.out.println(links);
getRecursive(element.attr("abs:href"), flevel, executor);
}
}
});
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
如果levels.length = 1,规则执行器运行良好,但如果levels.length>1将出现错误:线程异常 "pool-1-thread-138" java.util.concurrent.RejectedExecutionException
public static void main(String[] args) {
try {
ExecutorService executor = Executors.newFixedThreadPool(5);
new NewClass().getRecursive("http://www.java2s.com/", 0, executor);
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
if (executor.isTerminated()) {
JOptionPane.showMessageDialog(null, "Success");
}
} catch (Exception ex) {
Logger.getLogger(NewClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
问题是您在调用 executor.shutdown()
之后调用 executor.execute
。 awaitTermination
方法仅等待调用 shutdown
之前提交的任务。
这就是发生这种情况的原因:
- 假设程序在线程
main
上启动。 executor.execute
的第一个电话是在main
。- 假设执行程序现在在
thread-pool-1
上运行,它还调用executor.execute
。 - 但在执行这些新任务之前,我们跳回到
main
并调用executor.shutdown
。 - 执行器可能会再次开始执行任务,这次可能是
thread-pool-2
,它会尝试调用executor.execute
。但是,executor.shutdown()
已经被调用,因此抛出java.util.concurrent.RejectedExecutionException
。
有几种方法可以解决这个问题:
- 在这种情况下使用执行器可能有点矫枉过正;只做单线程可能就足够了。
- 也许可以重构代码,以便最后的
executor.execute
可以调用executor.shutdown
。但是,如果没有明确的最后调用,这将是不可能的。 如果您绝对需要在主线程之外执行此操作,您可以在其自己的线程中执行整个递归调用:
public static void main(String[] args) { try { ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(new Runnable() { @Override public void run() { NewClass.getRecursive("http://www.java2s.com/", 0); } }); executor.shutdown(); executor.awaitTermination(1, TimeUnit.HOURS); if (executor.isTerminated()) { JOptionPane.showMessageDialog(null, "Success"); } } catch (Exception ex) { Logger.getLogger(NewClass.class.getName()).log(Level.SEVERE, null, ex); } }
和
private static class NewClass { static String levels[] = { "div.col-md-9 li a", "div#sidebar ul li a" }; static String links = ""; private static void getRecursive(String href, int level) { if (level > levels.length - 1) { return; } Document doc; try { doc = Jsoup.connect(href).get(); Elements elements = doc.select(levels[level]); final int flevel = ++level; for (final Element element : elements) { if (!element.attr("href").isEmpty()) { links += element.attr("abs:href") + "\n"; System.out.println(links); getRecursive(element.attr("abs:href"), flevel); } } } catch (IOException e1) { e1.printStackTrace(); } } }
您关闭ExecutorService
后无法提交任何新任务,递归似乎在您处理完所有级别后停止(之后您不提交任何新任务),您可以这样做:
if (level > levels.length - 1) {
executor.shutdown();
return;
}