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

时间:2014-12-28 04:42:47

标签: 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();
}

我试图限制的方式是通过为每个新线程增加一个全局变量,然后在每个新线程结束时将其自身缩小,认为循环将暂停并等待变量足够低以创建新的像这样的线程

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();
}

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

3 个答案:

答案 0 :(得分: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();
}

信号量有5个“许可”,这意味着对s.acquire()的前5次调用将立即成功。但在此之后,s.acquire()只有在有相应的s.release()时才能成功。许可数量在每个线程开始之前减少一个(s.acquire()),并在每个线程退出之前备份一个(s.release())。由于许可证的数量永远不会是负数,因此已启动但尚未退出的线程数永远不会超过5个。

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

答案 1 :(得分:1)

Hovercraft Full Of Eels用FixedThreadPool回答了这个问题,我不知道如何发表评论,所以我只是自己回答并给了他学分。我刚刚创建了一个扩展Thread的类,并将我的代理检查代码放在类的run()方法中,然后我的旧代码被替换为了。

ExecutorService executor = Executors.newFixedThreadPool(Integer.parseInt(textField.getText()));
for(int i = 0; i < proxies.size(); i++){
    final String s = proxies.get(i);
    Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(s.split(":")[0], Integer.parseInt(s.split(":")[1])));
    Thread thread = new CheckThread(proxy, 5000, i);
    executor.execute(thread);
}
executor.shutdown();

答案 2 :(得分:0)

您可以将for循环更改为while循环。

while (true) {
    while (runningThreads <= 5) {
        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();
    }

    Thread.sleep(100);
}

外部while (true)循环将使检查继续运行,并在运行的线程低于5时创建新线程。