【问题标题】:Why is it that fewer threads finished than started in ExecutorService?为什么在 ExecutorService 中完成的线程比启动的线程少?
【发布时间】:2019-01-02 10:23:44
【问题描述】:

据我了解,ExecutorService 创建了一个可以重用的线程池。我创建了一个大小为 128 的池,并让它执行 128 个可运行任务。虽然它启动了 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();
    }
}
}

【问题讨论】:

  • 记录一下:为什么您的 RunTask 类究竟要扩展 Thread,而不是简单地实现 Runnable?
  • 除此之外,我们可能还需要一个真正的minimal reproducible example。您所描述的没有意义-当服务启动任务并且它们确实打印“开始”时,迟早,它们都应该打印“完成”……无论如何。所以,为了帮助你,你应该让我们以某种方式重现这个问题。
  • 另外,代码有问题:while(i=0;i
  • 我对多线程没有太多经验,所以我扩展了 Thread,因为它是教程的一部分。在原始代码中,我正在创建与 LAN 上不同设备(给定 ip_addresses)的 WebDriver 连接,每个设备都有相同的网页并与这些元素交互。我会看看我是否可以创建一个复制品并尽快更新

标签: java multithreading selenium-webdriver executorservice


【解决方案1】:

当我尝试上述代码时,我发现异常。

Class not found com/gargoylesoftware/htmlunit/WebWindowListener

通过异常处理,它按预期工作。为了解决找不到类的错误,我添加了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());
}

【讨论】:

  • 感谢您的推荐。似乎我的问题的根本原因是 socketTimeOutExceptions: read timeouts。看起来我不正确地关闭了我的驱动程序。
【解决方案2】:

如果您将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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-25
    • 2010-09-09
    • 1970-01-01
    • 2015-06-22
    • 2021-09-20
    • 2017-07-19
    • 2012-11-29
    • 2017-10-25
    相关资源
    最近更新 更多