下面来分析线程执行类,线程池ThreadPool类

对该类的理解需要对java的线程池比较熟悉

该类引用了一个内部类

/**
* The lazily constructed LazyThreadPool instance.
*/
private LazyThreadPool lazyThreadPool;

该成员实现了单例模式,即该对象只有一个实例,属于懒汉式单例模式,当实例化该成员时,启用了线程同步机制

/**
* Shut down the {@link ThreadPool}. After this returns
* {@link ThreadPool#submit(TimedCancelable)} will return null.
*
* @param interrupt {@code true} if the threads executing tasks task should
* be interrupted; otherwise, in-progress tasks are allowed to complete
* normally.
* @param waitMillis maximum amount of time to wait for tasks to complete.
* @return {@code true} if all the running tasks terminated and
* {@code false} if the some running task did not terminate.
* @throws InterruptedException if interrupted while waiting.
*/
synchronized boolean shutdown(boolean interrupt, long waitMillis)
throws InterruptedException {
isShutdown = true;
if (lazyThreadPool == null) {
return true;
} else {
return lazyThreadPool.shutdown(interrupt, waitMillis);
}
} /**
* Return a LazyThreadPool.
*/
private synchronized LazyThreadPool getInstance() {
if (lazyThreadPool == null) {
lazyThreadPool = new LazyThreadPool();
}
return lazyThreadPool;
}

线程提交方法如下

/**
* Submit a {@link Cancelable} for execution and return a
* {@link TaskHandle} for the running task or null if the task has not been
* accepted. After {@link ThreadPool#shutdown(boolean, long)} returns this
* will always return null.
*/
public TaskHandle submit(Cancelable cancelable) {
if (isShutdown) {
return null;
}
if (cancelable instanceof TimedCancelable && maximumTaskLifeMillis != 0L) {
return getInstance().submit((TimedCancelable) cancelable);
} else {
return getInstance().submit(cancelable);
}
}

这里针对Cancelable对象类型和TimedCancelable类型提交到了不同的方法(多态)

提交Cancelable类型对象比较简单,提交任务后获取操作句柄

/**
* 提交任务2 获得操作句柄
* Submit a {@link Cancelable} for execution and return a
* {@link TaskHandle} for the running task or null if the task has not been
* accepted. After {@link LazyThreadPool#shutdown(boolean, long)} returns
* this will always return null.
*/
TaskHandle submit(Cancelable cancelable) {
try {
// taskFuture is used to cancel 'cancelable' and to determine if
// 'cancelable' is done.
Future<?> taskFuture = completionService.submit(cancelable, null);
return new TaskHandle(cancelable, taskFuture, clock.getTimeMillis());
} catch (RejectedExecutionException re) {
if (!executor.isShutdown()) {
LOGGER.log(Level.SEVERE, "Unable to execute task", re);
}
return null;
}
}

而提交TimedCancelable类型对象则相对比较复杂

基本思路是,首先启动一个延迟执行的线程,即在指定的时间延迟后执行TimedCancelable类型对象的timeout()方法,即取消另外一个线程的执行,即超时检测线程;

然后启动另外一个线程执行TimedCancelable类型对象的run()方法,同时执行完毕后,则同时取消上面的超时检测线程(如果指定时间内未执行完毕,则由超时检测线程来取消执行)。

这里我们可以类比于守护线程与用户线程的关系,前面的超时检测线程好比守护线程,后者好比用户线程,当用户线程执行完毕后,守护线程也就没有存在的必要了

提交TimedCancelable类型对象方法如下

 /**
* 提交任务1
* Submit a {@link TimedCancelable} for execution and return a
* {@link TaskHandle} for the running task or null if the task has not been
* accepted. After {@link LazyThreadPool#shutdown(boolean, long)} returns
* this will always return null.
*/
TaskHandle submit(TimedCancelable cancelable) {
try {
// When timeoutTask is run it will cancel 'cancelable'.
TimeoutTask timeoutTask = new TimeoutTask(cancelable); // Schedule timeoutTask to run when 'cancelable's maximum run interval
// has expired.
// timeoutFuture will be used to cancel timeoutTask when 'cancelable'
// completes.
//延迟执行
Future<?> timeoutFuture = timeoutService.schedule(timeoutTask,
maximumTaskLifeMillis, TimeUnit.MILLISECONDS); //cancelable执行完毕之后,超时线程不再执行
// cancelTimeoutRunnable runs 'cancelable'. When 'cancelable' completes
// cancelTimeoutRunnable cancels 'timeoutTask'. This saves system
// resources. In addition it prevents timeout task from running and
// calling cancel after 'cancelable' completes successfully.
CancelTimeoutRunnable cancelTimeoutRunnable =
new CancelTimeoutRunnable(cancelable, timeoutFuture); // taskFuture is used to cancel 'cancelable' and to determine if
// 'cancelable' is done.
Future<?> taskFuture =
completionService.submit(cancelTimeoutRunnable, null);
TaskHandle handle =
new TaskHandle(cancelable, taskFuture, clock.getTimeMillis()); // TODO(strellis): test/handle timer pop/cancel before submit. In
// production with a 30 minute timeout this should never happen.
timeoutTask.setTaskHandle(handle);
return handle;
} catch (RejectedExecutionException re) {
if (!executor.isShutdown()) {
LOGGER.log(Level.SEVERE, "Unable to execute task", re);
}
return null;
}
}

首先构造超时检测任务对象,该类为静态内部类

/**
* 静态内部类 检测线程超时
* A task that cancels another task that is running a {@link TimedCancelable}.
* The {@link TimeoutTask} should be scheduled to run when the interval for
* the {@link TimedCancelable} to run expires.
*/
private static class TimeoutTask implements Runnable {
final TimedCancelable timedCancelable;
private volatile TaskHandle taskHandle; TimeoutTask(TimedCancelable timedCancelable) {
this.timedCancelable = timedCancelable;
} public void run() {
if (taskHandle != null) {
timedCancelable.timeout(taskHandle);
}
} void setTaskHandle(TaskHandle taskHandle) {
this.taskHandle = taskHandle;
}
}

然后延迟执行该线程,获得Future<?> timeoutFuture线程句柄

// Schedule timeoutTask to run when 'cancelable's maximum run interval
// has expired.
// timeoutFuture will be used to cancel timeoutTask when 'cancelable'
// completes.
//延迟执行
Future<?> timeoutFuture = timeoutService.schedule(timeoutTask,
maximumTaskLifeMillis, TimeUnit.MILLISECONDS);

然后构造CancelTimeoutRunnable对象,传入TimedCancelable类型对象和Future<?> timeoutFuture线程句柄

//cancelable执行完毕之后,超时线程不再执行
// cancelTimeoutRunnable runs 'cancelable'. When 'cancelable' completes
// cancelTimeoutRunnable cancels 'timeoutTask'. This saves system
// resources. In addition it prevents timeout task from running and
// calling cancel after 'cancelable' completes successfully.
CancelTimeoutRunnable cancelTimeoutRunnable =
new CancelTimeoutRunnable(cancelable, timeoutFuture);

内部类LazyThreadPool的内部类CancelTimeoutRunnable

/**
* 内部类LazyThreadPool的内部类1
* 执行TimedCancelable cancelable的run方法
* 执行完毕后取消超时线程
* A {@link Runnable} for running {@link TimedCancelable} that has been
* guarded by a timeout task. This will cancel the timeout task when the
* {@link TimedCancelable} completes. If the timeout task has already run,
* then canceling it has no effect.
*/
private class CancelTimeoutRunnable implements Runnable {
private final Future<?> timeoutFuture;
private final TimedCancelable cancelable; /**
* Constructs a {@link CancelTimeoutRunnable}.
*
* @param cancelable the {@link TimedCancelable} this runs.
* @param timeoutFuture the {@link Future} for canceling the timeout task.
*/
CancelTimeoutRunnable(TimedCancelable cancelable, Future<?> timeoutFuture) {
this.timeoutFuture = timeoutFuture;
this.cancelable = cancelable;
} public void run() {
try {
cancelable.run();
} finally {
timeoutFuture.cancel(true);
timeoutService.purge();
}
}
}

上面的run方法执行cancelable对象的run方法,执行完毕后取消超时线程并清理队列任务

后面部分是提交任务并获取线程操作句柄

// taskFuture is used to cancel 'cancelable' and to determine if
// 'cancelable' is done.
Future<?> taskFuture =
completionService.submit(cancelTimeoutRunnable, null);
TaskHandle handle =
new TaskHandle(cancelable, taskFuture, clock.getTimeMillis()); // TODO(strellis): test/handle timer pop/cancel before submit. In
// production with a 30 minute timeout this should never happen.
timeoutTask.setTaskHandle(handle);

shutdown方法关闭线程池

/**
* 关闭线程池任务
* Shut down the LazyThreadPool.
* @param interrupt {@code true} if the threads executing tasks task should
* be interrupted; otherwise, in-progress tasks are allowed to
* complete normally.
* @param waitMillis maximum amount of time to wait for tasks to complete.
* @return {@code true} if all the running tasks terminated, or
* {@code false} if some running task did not terminate.
* @throws InterruptedException if interrupted while waiting.
*/
boolean shutdown(boolean interrupt, long waitMillis)
throws InterruptedException {
if (interrupt) {
executor.shutdownNow();
} else {
executor.shutdown();
}
if (timeoutService != null) {
timeoutService.shutdown();
}
try {
return executor.awaitTermination(waitMillis, TimeUnit.MILLISECONDS);
} finally {
completionExecutor.shutdownNow();
if (timeoutService != null) {
timeoutService.shutdownNow();
}
}
}

内部类LazyThreadPool的内部类CompletionTask用于获取线程结果

/**
* 内部类LazyThreadPool的内部类2
* 获取结果线程
* A task that gets completion information from all the tasks that run in a
* {@link CompletionService} and logs uncaught exceptions that cause the
* tasks to fail.
*/
private class CompletionTask implements Runnable {
private void completeTask() throws InterruptedException {
Future<?> future = completionService.take();
try {
future.get();
} catch (CancellationException e) {
LOGGER.info("Batch terminated due to cancellation.");
} catch (ExecutionException e) {
Throwable cause = e.getCause();
// TODO(strellis): Should we call cancelable.cancel() if we get an
// exception?
if (cause instanceof InterruptedException) {
LOGGER.log(Level.INFO, "Batch terminated due to an interrupt.",
cause);
} else {
LOGGER.log(Level.SEVERE, "Batch failed with unhandled exception: ",
cause);
}
}
} public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
completeTask();
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
LOGGER.info("Completion task shutdown.");
}
}
}

ThreadNamingThreadFactory为静态内部类,用于构造线程对象

/**
* A {@link ThreadFactory} that adds a prefix to thread names assigned
* by {@link Executors#defaultThreadFactory()} to provide diagnostic
* context in stack traces.
*/
private static class ThreadNamingThreadFactory implements ThreadFactory {
private final ThreadFactory delegate = Executors.defaultThreadFactory();
private final String namePrefix; ThreadNamingThreadFactory(String namePrefix) {
this.namePrefix = namePrefix + "-";
} public Thread newThread(Runnable r) {
Thread t = delegate.newThread(r);
t.setName(namePrefix + t.getName());
return t;
}
}

---------------------------------------------------------------------------

本系列企业搜索引擎开发之连接器connector系本人原创

转载请注明出处 博客园 刺猬的温驯

本人邮箱: chenying998179@163#com (#改为.)

本文链接 http://www.cnblogs.com/chenying99/p/3775701.html

企业搜索引擎开发之连接器connector(二十二)的更多相关文章

  1. 企业搜索引擎开发之连接器connector(十九)

    连接器是基于http协议通过推模式(push)向数据接收服务端推送数据,即xmlfeed格式数据(xml格式),其发送数据接口命名为Pusher Pusher接口定义了与发送数据相关的方法 publi ...

  2. 企业搜索引擎开发之连接器connector(十八)

    创建并启动连接器实例之后,连接器就会基于Http协议向指定的数据接收服务器发送xmlfeed格式数据,我们可以通过配置http代理服务器抓取当前基于http协议格式的数据(或者也可以通过其他网络抓包工 ...

  3. 企业搜索引擎开发之连接器connector(十六)

    本人有一段时间没有接触企业搜索引擎之连接器的开发了,连接器是涉及企业搜索引擎一个重要的组件,在数据源与企业搜索引擎中间起一个桥梁的作用,类似于数据库之JDBC,通过连接器将不同数据源的数据适配到企业搜 ...

  4. 企业搜索引擎开发之连接器connector(二十九)

    在哪里调用监控器管理对象snapshotRepositoryMonitorManager的start方法及stop方法,然后又在哪里调用CheckpointAndChangeQueue对象的resum ...

  5. 企业搜索引擎开发之连接器connector(二十八)

    通常一个SnapshotRepository仓库对象对应一个DocumentSnapshotRepositoryMonitor监视器对象,同时也对应一个快照存储器对象,它们的关联是通过监视器管理对象D ...

  6. 企业搜索引擎开发之连接器connector(二十六)

    连接器通过监视器对象DocumentSnapshotRepositoryMonitor从上文提到的仓库对象SnapshotRepository(数据库仓库为DBSnapshotRepository)中 ...

  7. 企业搜索引擎开发之连接器connector(二十五)

    下面开始具体分析连接器是怎么与连接器实例交互的,这里主要是分析连接器怎么从连接器实例获取数据的(前面文章有涉及基于http协议与连接器的xml格式的交互,连接器对连接器实例的设置都是通过配置文件操作的 ...

  8. 企业搜索引擎开发之连接器connector(二十四)

    本人在上文中提到,连接器实现了两种事件依赖的机制 ,其一是我们手动操作连接器实例时:其二是由连接器的自动更新机制 上文中分析了连接器的自动更新机制,即定时器执行定时任务 那么,如果我们手动操作连接器实 ...

  9. 企业搜索引擎开发之连接器connector(二十)

    连接器里面衔接数据源与数据推送对象的是QueryTraverser类对象,该类实现了Traverser接口 /** * Interface presented by a Traverser. Used ...

随机推荐

  1. postman tests实例记录(还没看,一些常用的)

    这段时间准备测试api接口,postman这个工具很是方便,特别是里面的tests的javascript脚本. 记录一下测试接口常用的tests验证的实例. 1.设置环境变量 postman.setE ...

  2. RouterOS SOCKS代理服务器(官方文档翻译)

    SOCKS 是基于TCP应用层协议穿透防火墙的代理服务器,即使防火墙阻止了一些应用端口,也能通过SOCKS代理穿透.SOCKS协议是独立于应用层的,因此可以用于WWW.FTP.Telnet等等. 来至 ...

  3. jquery文件的引入

    上节课说到,一般情况下,是库的文件,该库中都会抛出来构造函数或者对象 ,如果是构造函数,那么创建对象,如果是对象直接调用属性和方法 使用jquery第一步,先引入jquery,然后再写相应的jquer ...

  4. vuex语法精简(方便开发查阅)

    vuex语法精简(方便开发查阅) store结构 state Getter Mutation actions vuex语法精简(方便开发查阅) 本文只是方便开发的时候快速查阅到相关语法,想看详细内容请 ...

  5. 接口自动化(三)--读取json文件中的数据

    上篇讲到实际的请求数据放置在json文件内,这一部分记述一下python读取json文件的实现. 代码如下(代码做了简化,根据需要调优:可做一些容错处理): 1 import json 2 3 cla ...

  6. easyui制作进度条案例demo

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. Microsoft Office Professional Plus 2013全套

    Microsoft Office Professional Plus 2013全套产品,全激活版本 包括Access  Word  Excel  Powerpoint  Publisher  Skyd ...

  8. 如何解决JSP页面显示乱码问题

    一.JSP页面显示乱码 下面的显示JSP页面(display.jsp)就出现乱码: <html> <head> <title>JSP的中文处理</title& ...

  9. TabIndex 属性 Tabindex="-1" 与Tabindex="0"、任意数字 (收录)

    TabIndex 属性 Tabindex="-1" 与Tabindex="0".任意数字 html中的tabIndex属性可以设置键盘中的TAB键在控件中的移动 ...

  10. eclipse双击变量高亮显示开关

    在eclipse/myeclipse中如果不小心把变量的高亮显示弄丢了.可真是件愁人的事,不过看到这你就不用愁了 windows->   preferences-> java-> E ...