
com.iih5.actor.Actor Maven / Gradle / Ivy
/*
* Copyright 2016 xueyi ([email protected])
*
* The Smart-Actor Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.iih5.actor;
import com.iih5.actor.scheduler.LoopScheduledTask;
import com.iih5.actor.scheduler.ScheduledTask;
import com.iih5.actor.scheduler.TaskFutureListener;
import com.iih5.actor.util.GlobalConstant;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 并发包中核心的类,负责处理所有任务,并且保证同一Actor提交的任务
* 都在同一线程中顺序执行,每个Actor对应一个
* ActorExecutor但是同一个ActorExecutor 可以为多个Actor服务
* Actor可以切换ActorExecutor 切换时为了保证线程安全一致性
* 会改变Actor状态为ActorState.TRANSITIVE 处于此状态时,
* 任务不会马上提交执行,而是会先放入缓冲队列中等待状态恢复正常时下次任务激活执行
* */
public class Actor implements IActor {
protected volatile IActorExecutor executor;
private BlockingQueue waitQueue=new LinkedBlockingQueue();
private volatile ActorState state= ActorState.NORMAL;
private Lock lock=new ReentrantLock(true);
private ActorManager parent;
private ScheduledExecutorService scheduledExecutorService;
private Map> futures;
public Actor(ActorManager parent){
this.parent=parent;
this.scheduledExecutorService=parent.getScheduledExecutorService();
this.futures=new TreeMap>();
}
public IActorExecutor getExecutor(){
return executor;
}
/**
* 如果是切换Executor,在切换Executor之前,必须将State设置为SubmiterState.TRANSITIVE
* */
public void setExecutor(IActorExecutor executor){
lock.lock();
try {
if(executor==null){
throw new NullPointerException("任务处理器executor不能为空,否则提交的任务不能执行");
}
if(this.executor!=null&&this.executor.workThread()!=null&&this.executor!=executor){//切换Executor
System.err.println("Actor 切换线程:old={},new={} "+this.executor.workThread()+executor.workThread());
state= ActorState.TRANSITIVE;
transfer(executor);
state= ActorState.NORMAL;
}
this.executor=executor;
}finally{
lock.unlock();
}
}
/**
* 设置actor执行Executor
* 用于切换工作场景时,切换执行线程,比如用户进入某个房间,则要设置为房间的执行线程,这样就消除多线程的问题)
*
* @param executor
*/
public void switchExecutor(IActorExecutor executor) {
setExecutor(executor);
}
/**
* 将缓冲队列中的任务提交到executor的执行队列中
* */
private void transfer(IActorExecutor executor) {
if(state== ActorState.TRANSITIVE){//必须是过渡状态才允许此操作
for(Runnable task:waitQueue){
executor.submit(task);
}
}else{
throw new IllegalStateException("非"+ ActorState.TRANSITIVE+"状态不能执行此操作");
}
}
public ActorState getActorState() {
// TODO Auto-generated method stub
return state;
}
/**
* @param task 构造的Future
* @return true 过渡期任务,提交到缓冲waitQueue中 false 任务会直接提交到执行队列中,走executor.submit()流程
* */
private boolean executeTransTask(Runnable task) {
if(state== ActorState.TRANSITIVE){
lock.lock();
try{
//双重检查,避免多余锁开销,先判定为过渡状态加一次锁,然后再判断状态
if(state== ActorState.TRANSITIVE){
System.err.println("过渡期新任务:actor={}"+this.toString());
waitQueue.put(task);
return true;
}else{
return false;
}
}catch (Exception e){
System.err.println("处理过渡期任务异常"+e);
}finally {
lock.unlock();
}
}
return false;
}
/**
* 保证同一Session中的任务必须在同一线程中顺序执行
* 判断Submiter是否为过渡状态,如果是过渡状态
* 则任务不直接提交到Executor执行队列中,而且是提交到过渡任务队列中
* 当submiter切换Executor完毕后,将过渡任务队列中的内容提交到新的Executor执行。
* */
public Future> execute(Runnable task) {
FutureTask
© 2015 - 2025 Weber Informatics LLC | Privacy Policy