我正在创建一个代理检查器,我已经创建了一个前一个并且它是多线程的,但它为每个代理创建了一个新线程来检查,这就是我用这个做的,但当我去使用它时检查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();
}
我目前没有想法,所以任何帮助都会很棒。
答案 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时创建新线程。