Reputation: 85
I have an executor service that submits x amount of threads concurrently to do a long task. I need to be able to stop all the current threads that are running and prevent queued tasks from starting. I am trying to implement a way to handle stopping threads that are waiting for a synchronized method in which the runnable passes a list of strings back to the interface that called it.
@Override
public synchronized void FilterResults(List<String> Results) {
//System.out.println("Result found: " + Results.size());
try {
Set<String> hs = new HashSet<>();
hs.addAll(Results);
Results.clear();
Results.addAll(hs);
for (String tempURL : Results) {
//System.out.println("Found url: " + tempURL);
if (!isCompleted(tempURL) && !isQueued(tempURL) && !isRunning(tempURL)) {
System.out.println("Added: " + tempURL + " to queue.");
queueLink(tempURL);
startNewThread(tempURL);
}
}
}catch(Exception e) {
}
return;
}
private synchronized void startNewThread(String seedURL) {
if (!isCompleted(seedURL) && !isRunning(seedURL) ) {
if (completedSize("") + runningSize() > 99) {
Stop();
}
String tempProxy = "";
String tempPort = "";
if (UseProxies) {
String Proxy = grabFreeProxy();
String[] splitProxy = Proxy.split(":");
tempProxy = splitProxy[0]; // 004
tempPort = splitProxy[1]; // 034556
}
//System.out.println("Proxy: " + tempProxy);
//System.out.println("Port: " + tempPort);
execService.submit(new Crawl(seedURL, this, tempProxy, tempPort, UseProxies));
removeFromQueue(url);
}
}
@Override
public Collection<String> Stop() {
try {
execService.shutdown();
if (execService.awaitTermination(45, TimeUnit.SECONDS)) {
System.out.println("task completed");
} else {
execService.shutdownNow();
}
} catch (InterruptedException e) {
}
return PROFILES;
}
The Runnable
public class Crawl implements Runnable{
public void run() {
while(!Thread.currentThread().isInterrupted() && shutdown == false) {
try {
//System.out.println(crawler.queueSize());
Thread.sleep(100);
Crawl(url);
}catch (InterruptedException e) {
Thread.currentThread().interrupt(); // set interrupt flag
}
}
public void crawl(){
try {
submitResults(urls); //Calls FilterResults()
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
Thread.currentThread().interrupt();
}
crawler.removeUsedProxy(Proxy + ":" + Port);
this.shutdown();
}
}
When I call my shutdown method it takes 45 seconds+ is there anyway to reliably cancel the task without the long wait? This number grows as I have more threads, and since all the threads are blocking waiting to submit the results, it can take some time. If I cancel the task manually I do not care if the results are stored, I just need to be able to cancel. Any ideas?
Update I've tried
ExecutorService#shutdownNow
. It has not been reliable when it comes to killing the tasks that are still blocked on thesynchronized
method.
Upvotes: 1
Views: 129
Reputation: 85789
Looks like you need to use ExecutorService#shutdownNow
in case you don't want to wait and finish all the work and you'll receive a list with the tasks that weren't executed. You may use ExecutionService#awaitTermination
(with different parameters than 45 seconds) if you want/need to provide a time to wait for the tasks to finish.
Upvotes: 1