达芬奇幸运之门彩票网:关闭线程池,记录正在进行却未完成的任务,fasle positive and idempotent
来源:百度文库 编辑:九乡新闻网 时间:2024/04/25 16:43:14
使用TrackingExecutor 代理 ExecutorService,当取消任务时,未完成的task会被记录下来,以备下次启动继续执行。
public class TrackingExecutor extends AbstractExecutorService {
private final ExecutorService exec;
private final Set tasksCancelledAtShutdown =
Collections.synchronizedSet(new HashSet());
public TrackingExecutor(ExecutorService exec) {
this.exec = exec;
}
public void shutdown() {
exec.shutdown();
}
public List shutdownNow() {
return exec.shutdownNow();
}
public boolean isShutdown() {
return exec.isShutdown();
}
public boolean isTerminated() {
return exec.isTerminated();
}
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
return exec.awaitTermination(timeout, unit);
}
public List getCancelledTasks() {
if (!exec.isTerminated())
throw new IllegalStateException(/*...*/);
return new ArrayList(tasksCancelledAtShutdown);
}
public void execute(final Runnable runnable) {
exec.execute(new Runnable() {
public void run() {
try {
runnable.run();
} finally {
if (isShutdown()
&& Thread.currentThread().isInterrupted())
tasksCancelledAtShutdown.add(runnable);
}
}
});
}
}
public abstract class WebCrawler {
private volatile TrackingExecutor exec;
@GuardedBy("this") private final Set urlsToCrawl = new HashSet();
private final ConcurrentMap seen = new ConcurrentHashMap();
private static final long TIMEOUT = 500;
private static final TimeUnit UNIT = MILLISECONDS;
public WebCrawler(URL startUrl) {
urlsToCrawl.add(startUrl);
}
public synchronized void start() {
exec = new TrackingExecutor(Executors.newCachedThreadPool());
for (URL url : urlsToCrawl) submitCrawlTask(url);
urlsToCrawl.clear();
}
public synchronized void stop() throws InterruptedException {
try {
saveUncrawled(exec.shutdownNow());
if (exec.awaitTermination(TIMEOUT, UNIT))
saveUncrawled(exec.getCancelledTasks());
} finally {
exec = null;
}
}
protected abstract List processPage(URL url);
private void saveUncrawled(List uncrawled) {
for (Runnable task : uncrawled)
urlsToCrawl.add(((CrawlTask) task).getPage());
}
private void submitCrawlTask(URL u) {
exec.execute(new CrawlTask(u));
}
private class CrawlTask implements Runnable {
private final URL url;
CrawlTask(URL url) {
this.url = url;
}
private int count = 1;
boolean alreadyCrawled() {
return seen.putIfAbsent(url, true) != null;
}
void markUncrawled() {
seen.remove(url);
System.out.printf("marking %s uncrawled%n", url);
}
public void run() {
for (URL link : processPage(url)) {
if (Thread.currentThread().isInterrupted())
return;
submitCrawlTask(link);
}
}
public URL getPage() {
return url;
}
}
}
TrackingExecutor has an unavoidable race conditionthat could make it yield false positives: tasks that are identified as cancelledbut actually completed. This arises because the thread pool could beshut down between when the last instruction of the task executes and when thepool records the task as complete. This is not a problem if tasks are idempotent (if performing them twice has the sameeffect as performing them once), as they typically are in a web crawler.Otherwise, the application retrieving the cancelled tasks must be aware of thisrisk and be prepared to deal with false positives.
public class TrackingExecutor extends AbstractExecutorService {
private final ExecutorService exec;
private final Set
Collections.synchronizedSet(new HashSet
public TrackingExecutor(ExecutorService exec) {
this.exec = exec;
}
public void shutdown() {
exec.shutdown();
}
public List
return exec.shutdownNow();
}
public boolean isShutdown() {
return exec.isShutdown();
}
public boolean isTerminated() {
return exec.isTerminated();
}
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
return exec.awaitTermination(timeout, unit);
}
public List
if (!exec.isTerminated())
throw new IllegalStateException(/*...*/);
return new ArrayList
}
public void execute(final Runnable runnable) {
exec.execute(new Runnable() {
public void run() {
try {
runnable.run();
} finally {
if (isShutdown()
&& Thread.currentThread().isInterrupted())
tasksCancelledAtShutdown.add(runnable);
}
}
});
}
}
public abstract class WebCrawler {
private volatile TrackingExecutor exec;
@GuardedBy("this") private final Set
private final ConcurrentMap
private static final long TIMEOUT = 500;
private static final TimeUnit UNIT = MILLISECONDS;
public WebCrawler(URL startUrl) {
urlsToCrawl.add(startUrl);
}
public synchronized void start() {
exec = new TrackingExecutor(Executors.newCachedThreadPool());
for (URL url : urlsToCrawl) submitCrawlTask(url);
urlsToCrawl.clear();
}
public synchronized void stop() throws InterruptedException {
try {
saveUncrawled(exec.shutdownNow());
if (exec.awaitTermination(TIMEOUT, UNIT))
saveUncrawled(exec.getCancelledTasks());
} finally {
exec = null;
}
}
protected abstract List
private void saveUncrawled(List
for (Runnable task : uncrawled)
urlsToCrawl.add(((CrawlTask) task).getPage());
}
private void submitCrawlTask(URL u) {
exec.execute(new CrawlTask(u));
}
private class CrawlTask implements Runnable {
private final URL url;
CrawlTask(URL url) {
this.url = url;
}
private int count = 1;
boolean alreadyCrawled() {
return seen.putIfAbsent(url, true) != null;
}
void markUncrawled() {
seen.remove(url);
System.out.printf("marking %s uncrawled%n", url);
}
public void run() {
for (URL link : processPage(url)) {
if (Thread.currentThread().isInterrupted())
return;
submitCrawlTask(link);
}
}
public URL getPage() {
return url;
}
}
}
关闭线程池,记录正在进行却未完成的任务,fasle positive and idempotent
happiness and positive psychology
纪录片 轰炸正在进行:《精英飞行员惊心动魄的飞行任务》
How to develop and maintain a positive attitu...[]
独立线程池的作用及IO线程池 - 猪悟能'S博客 - 博客园
一次未完成的性爱
河南儿童被逼行乞 未完成任务遭剪舌打掉牙
河南儿童被逼行乞受凌虐 未完成任务遭剪舌
民生银行员工疑因未完成拉存款任务自杀身亡
国务院:未完成保障房任务城市政府禁建办公楼
国办:未完成保障房任务政府禁建办公楼
国务院:未完成保障房任务城市禁建政府办公楼
Paths to Happiness: 7 Real Life Stories of Personal Growth, Self-Improvement and Positive Change
线程池Demo
浅谈线程池(中):独立线程池的作用及IO线程池 - 老赵点滴 - 追求编程之美 - 博客园
民间金融正在进行最后的狂欢
地球上正在进行着五场看不见的战争
地球上正在进行着五场看不见的战争
线程的暂停与重新启动
C#教程:线程的优先权
C#线程挂起的问题
线程的挂起与继续
进程和线程的区别
MFC的进程和线程