package com.pjf.common.scheduler;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import com.pjf.common.log.LoggerUtil;
/**
* 多线程队列处理器<BR>
* 特点:按数据接收顺序处理,但对于同一K值的V数据处理,既保证顺序,也是线程安全的<BR>
* <B>要求:一个V对象唯一对应一个键值</B><BR>
* 功能类似扩展线程的处理,实现参考引擎的ServerWriter
*/
public class MultiThreadQueueWorker<K, V> implements IControl {
private final LinkedBlockingQueue<K> keyQueue = new LinkedBlockingQueue<K>();
private final ConcurrentHashMap<K, ValueQueueWrap<V>> key_ValueQueueWrap = new ConcurrentHashMap<K, ValueQueueWrap<V>>();
protected final String name;
private final Thread[] workers;
private volatile boolean running;
private final int warnSize;
private final IProcessor<K, V> processor;
public MultiThreadQueueWorker(String name, int threadNum, int warnSize, IProcessor<K, V> processor) {
this.name = name;
workers = new Thread[threadNum];
running = false;
this.warnSize = warnSize;
this.processor = processor;
for (int i = 0; i < workers.length; i++) {
String threadName = String.format("%s-Pool%d-Th%d", name, threadNum, i);
workers[i] = new Thread(new WorkRunnable(), threadName);
workers[i].setDaemon(true);
}
}
/**
* 只能开启一次,关闭后再开会抛异常
*/
@Override
public synchronized void start() {
if (!running) {
running = true;
for (int i = 0; i < workers.length; i++) {
workers[i].start();
}
LoggerUtil.infof("<MultiThreadQueueWorker> worker[%s] started, %d thread(s)", name, workers.length);
}
}
@Override
public synchronized void shutdown() {
if (running) {
running = false;
LoggerUtil.infof("<MultiThreadQueueWorker> shutting down worker[%s]", name);
for (int i = 0; i < workers.length; i++) {
workers[i].interrupt();
}
}
}
@Override
public boolean isRunning() {
return running;
}
public void accept(K key, V value) {
ValueQueueWrap<V> valueQueueWrap = key_ValueQueueWrap.get(key);
if (valueQueueWrap == null) {
valueQueueWrap = new ValueQueueWrap<V>();
ValueQueueWrap<V> tmp = key_ValueQueueWrap.putIfAbsent(key, valueQueueWrap);
if (tmp != null) {
valueQueueWrap = tmp;
}
}
synchronized (valueQueueWrap) {
int size = valueQueueWrap.valueQueue.size();
if (size == 0 && !valueQueueWrap.hasBeenAppendedToKeyQueue) {
if (keyQueue.offer(key)) {
valueQueueWrap.valueQueue.addLast(value);
valueQueueWrap.hasBeenAppendedToKeyQueue = true;
} else {
LoggerUtil.warnf("<MultiThreadQueueWorker> Workers[%s] offer fail while accept. key:%s", name, key);
}
} else {
if (size > 0 && size % warnSize == 0) {
LoggerUtil.warnf("<MultiThreadQueueWorker> Workers[%s] queue exceed warn size. key:%s size:%d",
name, key, size);
}
valueQueueWrap.valueQueue.addLast(value);
}
}
}
public void remove(K key) {
key_ValueQueueWrap.remove(key);
}
private void process() {
while (running) {
try {
K key = (K) keyQueue.take();
ValueQueueWrap<V> valueQueueWrap = key_ValueQueueWrap.get(key);
if (valueQueueWrap != null) {
V value = null;
synchronized (valueQueueWrap) {
value = valueQueueWrap.valueQueue.poll();
}
if (value != null) {
processor.process(key, value);
}
synchronized (valueQueueWrap) {
// 这里才重置hasAddedToKeyQueue,保证对K的处理是单线程的
valueQueueWrap.hasBeenAppendedToKeyQueue = false;
if (valueQueueWrap.valueQueue.size() > 0) {
if (keyQueue.offer(key)) {
valueQueueWrap.hasBeenAppendedToKeyQueue = true;
} else {
LoggerUtil
.warnf("<MultiThreadQueueWorker> Workers[%s] offer fail after process.", name);
}
}
}
}
} catch (Throwable t) {
if (running) {
LoggerUtil.errorf("<MultiThreadQueueWorker> Workers[%s] work process error.", t, name);
}
}
}
}
private class WorkRunnable implements Runnable {
@Override
public void run() {
process();
}
}
public interface IProcessor<K, V> {
public void process(K key, V value);
}
private static class ValueQueueWrap<V> {
public final LinkedList<V> valueQueue;
public volatile boolean hasBeenAppendedToKeyQueue;
public ValueQueueWrap() {
this.valueQueue = new LinkedList<V>();
this.hasBeenAppendedToKeyQueue = false;
}
}
}