Java - 如何在for循环中创建它们时限制一次运行的线程数

use*_*950 2 java multithreading limit

我正在制作一个代理检查器,我已经制作了一个前一个并且它是多线程的,但它为每个代理创建了一个新线程来检查,这就是我用这个做的,但当我去用它检查60k代理时它几乎融化了我的电脑哈哈.我试图限制一次运行的线程数量,但没有运气.我最初这样做的方式是这样的

for(int i = 0; i < proxies.size(); i++){
    final String s = proxies.get(i);
    new Thread(){
        public void run(){
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(s.split(":")[0], Integer.parseInt(s.split(":")[1])));
            if(checkProxy(proxy, 5000))
                textArea_1.setText(textArea_1.getText() + s + "\n");
            progress++;
            progressBar.setValue(progress);
        }
    }.start();
}
Run Code Online (Sandbox Code Playgroud)

我试图限制的方式是通过为每个新线程增加一个全局变量,然后在每个新线程结束时使用它自己认为循环会暂停并等待变量足够低以创建一个新线程,如此

for(int i = 0; i < proxies.size() && runningThreads <= 5; i++){
    runningThreads++;
    final String s = proxies.get(i);
    new Thread(){
        public void run(){
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(s.split(":")[0], Integer.parseInt(s.split(":")[1])));
            if(checkProxy(proxy, 5000))
                textArea_1.setText(textArea_1.getText() + s + "\n");
            progress++;
            progressBar.setValue(progress);
            runningThreads--;
        }
    }.start();
}
Run Code Online (Sandbox Code Playgroud)

我目前没有想法,所以任何帮助都会很棒.

小智 5

你可以使用这样的东西:

Semaphore s = new Semaphore(5);
for (int i = 0; i < proxies.size(); i++) {
  s.acquire();
  new Thread() {
    public void run() {
      try {
        ...proxy stuff...
      } finally {
        s.release();
      }
    }
  }.start();
}
Run Code Online (Sandbox Code Playgroud)

信号量有5个"许可证",这意味着前5个呼叫s.acquire()将立即成功.但在那之后,s.acquire()只有在相应的情况下才能成功s.release().许可数量s.acquire()在每个线程启动之前下降一(),并s.release()在每个线程退出之前备份一().由于许可证的数量永远不会是负数,因此已启动但尚未退出的线程数永远不会超过5.

您还可以使用Executors.newFixedThreadPool(5)显式创建大小为5的线程池.如果任务数量非常大,那么对于线程池,您必须考虑限制可以排队的任务数量,也许使用ThreadPoolExecutor.上面的信号量解决方案没有这个问题,因为它没有排队.