九、串行线程封闭(Serial Thread Confinement)
1、核心思想
通过将多个并发的任务存入队列实现任务的串行化,并为这些串行化的任务创建唯一的一个工作线程进行处理。
本质:使用一个开销更小的锁(队列锁)去替代另一个可能开销更大的锁(非线程安全对象引用的锁)
2、适用场景
a、需要使用非线程安全对象,但又不希望引入锁。
b、任务的执行涉及I/O操作,不希望过多的I/O线程增加上下文切换
3、是生产消费者模式的一个例子。
/**
* 对任务处理的抽象
* @author huzhiqiang
*
* @param <T>
* 任务的类型
* @param <V>
* 任务处理结果的类型
*/
public interface TaskProcssor<T, V> {
V doProcess(T task) throws Exception;
}
public class TerminatableWorkerThread<T, V> extends AbstractTerminatableThread {
private final BlockingQueue<Runnable> workQueue;
//负责正真执行任务的对象
private final TaskProcssor<T, V> taskProcssor;
public TerminatableWorkerThread(BlockingQueue<Runnable> workQueue, TaskProcssor<T, V> taskProcssor) {
super();
this.workQueue = workQueue;
this.taskProcssor = taskProcssor;
}
public Future<V> submit(final T task) throws InterruptedException{
Callable<V> callable = new Callable<V>() {
@Override
public V call() throws Exception {
return taskProcssor.doProcess(task);
}
};
FutureTask<V> ft = new FutureTask<V>(callable);
workQueue.put(ft);
terminationToken.reservations.incrementAndGet();
return ft;
}
@Override
protected void doRun() throws Exception {
Runnable ft = workQueue.take();
try {
ft.run();
} finally{
terminationToken.reservations.decrementAndGet();
}
}
}
public abstract class AbstractSerializer<T, V> {
private final TerminatableWorkerThread<T, V> workerThread;
public AbstractSerializer(BlockingQueue<Runnable> workQueue, TaskProcssor<T, V> taskProcssor) {
super();
this.workerThread = new TerminatableWorkerThread<>(workQueue, taskProcssor);
}
/**
* 留给子类实现。用于根据指定参数生成相应的任务实例
* @param params
* @return
*/
public abstract T makeTask(Object... params);
/**
* 对外暴露的方法
* @param params
* @return
* @throws InterruptedException
*/
public Future<V> service(Object... params) throws InterruptedException{
T task = makeTask(params);
Future<V> resultPromise = workerThread.submit(task);
return resultPromise;
}
public void init(){
workerThread.start();
}
public void shutdown(){
workerThread.terminate();
}
}
public class Main {
public static void main(String[] args) throws InterruptedException, ExecutionException {
SomeService ss = new SomeService();
ss.init();
Future<String> result = ss.doSomething("serial Thread confinement", 1);
Thread.sleep(50);
System.out.println(result.get());
ss.shutdown();
}
private static class Task{
private final int id;
private final String message;
public Task(int id, String message) {
this.id = id;
this.message = message;
}
}
private static class SomeService extends AbstractSerializer<Task, String>{
public SomeService(){
super(new ArrayBlockingQueue<>(100), new TaskProcssor<Task, String>() {
@Override
public String doProcess(Task task) throws Exception {
System.out.println("[" + task.id + "]: " + task.message);
return task.message + " accepted.";
}
});
}
@Override
public Task makeTask(Object... params) {
String message = (String) params[0];
int id = (int) params[1];
return new Task(id, message);
}
public Future<String> doSomething(String message, int id) throws InterruptedException{
Future<String> result = null;
result = service(message, id);
return result;
}
}
}