为什么在 ExecutorService 中完成的线程比启动的线程少?
Why is it that fewer threads finished than started in ExecutorService?
据我了解,ExecutorService 创建了一个可以重复使用的线程池。我创建了一个大小为 128 的池并让它执行 128 个 Runnable 任务。虽然它启动了 128 个线程(通过打印 "started"),但只打印了 10 个 "finished"。
为什么会这样?完成的线程是否在其他线程仍然存在的情况下被重用?还是我的线程根本没有完成?
编辑:
添加了我的代码,但我无法重现结果。我确实发现,但是当我对保存网站进行过多访问时,我会遇到 socketTimeoutException。
下面是我的代码示例:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
public class Test {
static class TestConnection extends Thread{
@Override
public void run() {
System.out.println("Started "+this.getName());
WebDriver driver = new HtmlUnitDriver(true);
driver.get("http://google.com");
//System.out.println(driver.getCurrentUrl());
driver.findElement(By.tagName("html"));
System.out.println("Finished "+this.getName());
}
}
public static void main(String args[]) {
ExecutorService pool = Executors.newFixedThreadPool(128);
for(int i=0; i < 32;i++){
TestConnection task = new TestConnection();
pool.execute(task);
}
pool.shutdown();
try {
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
如果您将 while
(无效)更改为 for
,它可以正常工作。
final int count = 128;
final boolean[] finished = new boolean[count];
class RunTask extends Thread {
private final int i;
public RunTask(int i) {
this.i = i;
}
public void run() {
//System.out.println("start " + this.getName());
//Do stuff. lots of I/O bound
System.out.println("finished " + i);
finished[i] = true;
}
}
public void test() throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(128);
for (int i = 0; i < count; i++) {
RunTask task = new RunTask(i);
pool.execute(task);
}
pool.shutdown();
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
for(int i = 0; i < count; i++) {
if(!finished[i]) {
System.out.println("NOT FINISHED! "+i);
}
}
}
这不会打印 NOT FINISHED
。
当我尝试上面的代码时,我发现了异常。
Class not found com/gargoylesoftware/htmlunit/WebWindowListener
通过异常处理,它按预期工作。为了解决 class not found 错误,我添加了 htmlunit driver dependency 并且它工作正常。
你的代码中缺少的一件事是你需要完全驱动否则你下次可能会遇到 websocket 错误运行,因为之前的执行没有正确终止.以下是工作代码:
@Override
public void run() {
System.out.println("Started "+this.getName());
try {
WebDriver driver = new HtmlUnitDriver(true);
driver.get("http://google.com");
//System.out.println(driver.getCurrentUrl());
driver.findElement(By.tagName("html"));
driver.quit();
} catch (Throwable e) {
System.err.println(this.getName() + " " +e.getMessage());
}
System.out.println("Finished "+this.getName());
}
据我了解,ExecutorService 创建了一个可以重复使用的线程池。我创建了一个大小为 128 的池并让它执行 128 个 Runnable 任务。虽然它启动了 128 个线程(通过打印 "started"),但只打印了 10 个 "finished"。 为什么会这样?完成的线程是否在其他线程仍然存在的情况下被重用?还是我的线程根本没有完成?
编辑: 添加了我的代码,但我无法重现结果。我确实发现,但是当我对保存网站进行过多访问时,我会遇到 socketTimeoutException。
下面是我的代码示例:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
public class Test {
static class TestConnection extends Thread{
@Override
public void run() {
System.out.println("Started "+this.getName());
WebDriver driver = new HtmlUnitDriver(true);
driver.get("http://google.com");
//System.out.println(driver.getCurrentUrl());
driver.findElement(By.tagName("html"));
System.out.println("Finished "+this.getName());
}
}
public static void main(String args[]) {
ExecutorService pool = Executors.newFixedThreadPool(128);
for(int i=0; i < 32;i++){
TestConnection task = new TestConnection();
pool.execute(task);
}
pool.shutdown();
try {
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
如果您将 while
(无效)更改为 for
,它可以正常工作。
final int count = 128;
final boolean[] finished = new boolean[count];
class RunTask extends Thread {
private final int i;
public RunTask(int i) {
this.i = i;
}
public void run() {
//System.out.println("start " + this.getName());
//Do stuff. lots of I/O bound
System.out.println("finished " + i);
finished[i] = true;
}
}
public void test() throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(128);
for (int i = 0; i < count; i++) {
RunTask task = new RunTask(i);
pool.execute(task);
}
pool.shutdown();
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
for(int i = 0; i < count; i++) {
if(!finished[i]) {
System.out.println("NOT FINISHED! "+i);
}
}
}
这不会打印 NOT FINISHED
。
当我尝试上面的代码时,我发现了异常。
Class not found com/gargoylesoftware/htmlunit/WebWindowListener
通过异常处理,它按预期工作。为了解决 class not found 错误,我添加了 htmlunit driver dependency 并且它工作正常。
你的代码中缺少的一件事是你需要完全驱动否则你下次可能会遇到 websocket 错误运行,因为之前的执行没有正确终止.以下是工作代码:
@Override
public void run() {
System.out.println("Started "+this.getName());
try {
WebDriver driver = new HtmlUnitDriver(true);
driver.get("http://google.com");
//System.out.println(driver.getCurrentUrl());
driver.findElement(By.tagName("html"));
driver.quit();
} catch (Throwable e) {
System.err.println(this.getName() + " " +e.getMessage());
}
System.out.println("Finished "+this.getName());
}