关于线程超时没有太多的操作,现在只有一个简单的思路,那就是开启一个线程轮训监听所有线程池。
刚好最近在做一个项目,需要一对多进行轮训和监听,需要用到超时处理,因此特意看了一下,关键的就是开启线程,轮训查询线程执行时间,超时了直接关闭,也可以选择重开线程。
class TEST{
private static final int MAX_WAIT_TIME = 8000;
private static final int LOOP_TIME_OUT = 1000;
private static final int CORE_POOL_SIZE = 1;
private static final int INITIAL_DELAY_TIME = 0;
private static final int PERIOD_TIME = 30000;
private OnDataListener onDataListener;//数据回调处理
private OnTimeOutListener onTimeOutListener;//超时处理
private SparseArray<ScheduledThreadPoolExecutor> scheduledThreadPoolExecutor = new SparseArray<>(); //线程池集合
private SparseArray<RunnableScheduledFuture> aliveThreadFutureMap = new SparseArray<>(); //线程的对象集合
private ConcurrentMap<Integer, Long> aliveThreadRefreshTimeMap = new ConcurrentHashMap<>(); //每次线程执行时间
private SparseIntArray mThreadKeySparse = new SparseIntArray(); //线程id集合
private SparseArray<CollectBean> collectBeanSparseArray = new SparseArray<>(); //线程
private int mThreadTaskNum = 0;//当前一共开了多少线程
private void initData() {
createTimeOutLoopTask();
}
private void addScheduledThreadPool(int key) {
scheduledThreadPoolExecutor.put(key, ExecutorUtil.getInstance().newScheduledThreadPool(CORE_POOL_SIZE));
}
private void createTimeOutLoopTask() {
new Thread(() -> {
try {
Log.i("test", "aliveThreadRefreshTimeMap=" + aliveThreadRefreshTimeMap.size());
if (aliveThreadRefreshTimeMap.size() > 0) {
for (int i = 0; i < mThreadKeySparse.size(); i++) {
int mThreadKey = mThreadKeySparse.valueAt(i);
long currentTime = System.currentTimeMillis();
long refreshTimes = currentTime - aliveThreadRefreshTimeMap.get(mThreadKey);
Log.i("test", mThreadKey + "==refreshTimes=" + refreshTimes);
if (refreshTimes > MAX_WAIT_TIME) {
closeData(mThreadKey);
if (onTimeOutListener != null) { onTimeOutListener.onTimeOut(collectBeanSparseArray.get(mThreadKey));
}
}
}
Thread.sleep(LOOP_TIME_OUT);
} else {
Thread.sleep(MAX_WAIT_TIME);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}).start();
}
public void openData(CollectBean collectBean) { //CollectBean 传入的对象控制着有几个线程池
openModbusData(collectBean, INITIAL_DELAY_TIME, PERIOD_TIME);
}
private void openData(CollectBean collectBean, int initialDelay, int period) {
Log.i("gss", "openModbusData="+collectBean.getThreadKey() );
if (mThreadKeySparse.indexOfValue(collectBean.getThreadKey()) < 0) {
addScheduledThreadPool(collectBean.getThreadKey());
}
collectBean.setTaskKey(mThreadTaskNum);
aliveThreadFutureMap.put(mThreadTaskNum, (RunnableScheduledFuture) scheduledThreadPoolExecutor.get(collectBean.getThreadKey())
.scheduleAtFixedRate(workerThread(collectBean, modbus, mThreadTaskNum), initialDelay, period, TimeUnit.MILLISECONDS));
aliveThreadRefreshTimeMap.put(mThreadTaskNum, System.currentTimeMillis());
collectBeanSparseArray.put(collectBean.getThreadKey(), collectBean);
mThreadTaskNum++;
}
public void closeData(int mThreadKey) {
Objects.requireNonNull(aliveThreadFutureMap.get(mThreadKey)).cancel(true);
scheduledThreadPoolExecutor.get(mThreadKey).remove(aliveThreadFutureMap.get(mThreadKey));
aliveThreadRefreshTimeMap.remove(mThreadKey);
collectBeanSparseArray.remove(mThreadKey);
}
private Runnable workerThread(CollectBean collectBean, Modbus modbus,int i) {
return () -> {
try {
mThreadKeySparse.put(collectBean.getThreadKey(), i);//记录当前线程的KEY,当前循环到哪个线程
Thread.sleep(10000);//处理业务时间
aliveThreadRefreshTimeMap.replace(i, System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}
public void setOnDataListener(OnDataListener onDataListener) {
this.onDataListener = onDataListener;
}
public interface OnDataListener {
void onProgress(CollectBean dataMap);
}
public void setTimeOutListener(OnTimeOutListener onTimeOutListener) {
this.onTimeOutListener = onTimeOutListener;
}
public interface OnTimeOutListener {
void onTimeOut(CollectBean collectBean);
}
}