《Java并发库系列三》一newSingleThreadScheduledExecutor
【摘要】
newSingleThreadScheduledExecutor:产生一个ScheduledExecutorService对象,这个对象的线程池大小为1,如果任务多于一个,任务将按先后顺序执行。
1、继承结构
构造函数
包含一个定时的service
public static ScheduledExecutorService newSi...
newSingleThreadScheduledExecutor:产生一个ScheduledExecutorService对象,这个对象的线程池大小为1,如果任务多于一个,任务将按先后顺序执行。
1、继承结构
构造函数
包含一个定时的service
-
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
-
return new DelegatedScheduledExecutorService
-
(new ScheduledThreadPoolExecutor(1));
-
}
-
-
static class DelegatedScheduledExecutorService
-
extends DelegatedExecutorService
-
implements ScheduledExecutorService {
-
private final ScheduledExecutorService e;
-
DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
-
super(executor);
-
e = executor;
-
}
2、怎么保证只有一个线程
定时执行的时候调用这个方法,调用过程如下,注意看其中的注释,由上往下的调用顺序
-
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
-
long initialDelay,
-
long delay,
-
TimeUnit unit) {
-
if (command == null || unit == null)
-
throw new NullPointerException();
-
if (delay <= 0)
-
throw new IllegalArgumentException();
-
ScheduledFutureTask<Void> sft =
-
new ScheduledFutureTask<Void>(command,
-
null,
-
triggerTime(initialDelay, unit),
-
unit.toNanos(-delay));
-
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
-
sft.outerTask = t;
-
// 延迟执行
-
delayedExecute(t);
-
return t;
-
}
-
private void delayedExecute(RunnableScheduledFuture<?> task) {
-
if (isShutdown())
-
reject(task);
-
else {
-
// 加入任务队列
-
super.getQueue().add(task);
-
if (isShutdown() &&
-
!canRunInCurrentRunState(task.isPeriodic()) &&
-
remove(task))
-
task.cancel(false);
-
else
-
// 确保执行
-
ensurePrestart();
-
}
-
}
-
// 如果worker数量小于corePoolSize,创建新的线程,其他情况不处理
-
void ensurePrestart() {
-
int wc = workerCountOf(ctl.get());
-
if (wc < corePoolSize)
-
addWorker(null, true);
-
else if (wc == 0)
-
addWorker(null, false);
-
}
3、怎么保证时间可以定时执行
-
public ScheduledFuture<?> schedule(Runnable command,
-
long delay,
-
TimeUnit unit) {
-
if (command == null || unit == null)
-
throw new NullPointerException();
-
RunnableScheduledFuture<?> t = decorateTask(command,
-
new ScheduledFutureTask<Void>(command, null,
-
triggerTime(delay, unit)));
-
delayedExecute(t);
-
return t;
-
}
在每次执行的时候会把下一次执行的时间放进任务中
-
private long triggerTime(long delay, TimeUnit unit) {
-
return triggerTime(unit.toNanos((delay < 0) ? 0 : delay));
-
}
-
-
/**
-
* Returns the trigger time of a delayed action.
-
*/
-
long triggerTime(long delay) {
-
return now() +
-
((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay));
-
}
FutureTask 定时是通过LockSupport.parkNanos(this, nanos);LockSupport.park(this);
-
private int awaitDone(boolean timed, long nanos)
-
throws InterruptedException {
-
final long deadline = timed ? System.nanoTime() + nanos : 0L;
-
WaitNode q = null;
-
boolean queued = false;
-
for (;;) {
-
if (Thread.interrupted()) {
-
removeWaiter(q);
-
throw new InterruptedException();
-
}
-
-
int s = state;
-
if (s > COMPLETING) {
-
if (q != null)
-
q.thread = null;
-
return s;
-
}
-
else if (s == COMPLETING) // cannot time out yet
-
Thread.yield();
-
else if (q == null)
-
q = new WaitNode();
-
else if (!queued)
-
queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
-
q.next = waiters, q);
-
else if (timed) {
-
nanos = deadline - System.nanoTime();
-
if (nanos <= 0L) {
-
removeWaiter(q);
-
return state;
-
}
-
//注意这里
-
LockSupport.parkNanos(this, nanos);
-
}
-
else //注意这里
-
LockSupport.park(this);
-
}
-
}
总结:Executor是通过将任务放在队列中,生成的futureTask。然后将生成的任务在队列中排序,将时间最近的需要出发的任务做检查。如果时间不到,就阻塞线程到下次出发时间。
注意:newSingleThreadScheduledExecutor只会有一个线程,不管你提交多少任务,这些任务会顺序执行,如果发生异常会取消下面的任务,线程池也不会关闭,注意捕捉异常
4、使用
-
ScheduledExecutorService single = Executors.newSingleThreadScheduledExecutor();
-
Runnable runnable1 = () -> {
-
try {
-
Thread.sleep(4000);
-
System.out.println("11111111111111");
-
-
} catch (InterruptedException e) {
-
e.printStackTrace();
-
}
-
};
-
Runnable runnable2 = () -> {
-
try {
-
Thread.sleep(4000);
-
System.out.println("222");
-
-
} catch (InterruptedException e) {
-
e.printStackTrace();
-
}
-
};
-
single.scheduleWithFixedDelay(runnable1,0,1, TimeUnit.SECONDS);
-
single.scheduleWithFixedDelay(runnable2,0,2, TimeUnit.SECONDS);
-
11111111111111
-
222
-
11111111111111
-
222
-
11111111111111
在项目中要注意关闭线程池
-
actionService = Executors.newSingleThreadScheduledExecutor();
-
actionService.scheduleWithFixedDelay(() -> {
-
try {
-
Thread.currentThread().setName("robotActionService");
-
Integer robotId = robotQueue.poll();
-
if (robotId == null) {
-
// 关闭线程池
-
actionService.shutdown();
-
} else {
-
int aiLv = robots.get(robotId);
-
if (actionQueueMap.containsKey(aiLv)) {
-
ActionQueue actionQueue = actionQueueMap.get(aiLv);
-
actionQueue.doAction(robotId);
-
}
-
}
-
} catch (Exception e) {
-
// 捕捉异常
-
LOG.error("",e);
-
}
-
}, 1, 1, TimeUnit.SECONDS);
欢迎转载,我是香菜,谢谢。欢迎加入QQ群:632603498,一起学习
文章来源: gamwatcher.blog.csdn.net,作者:香菜聊游戏,版权归原作者所有,如需转载,请联系作者。
原文链接:gamwatcher.blog.csdn.net/article/details/88536377
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)