Callback.java
package async;
@FunctionalInterface
public interface Callback<T> {
void call(T t);
}
ChannelFuture.java
package org.example.async;
import java.util.concurrent.ExecutorService;
public interface ChannelFuture<IN, OUT> {
FutureTask addListener(int hashId, Task<IN, OUT> task, IN input, Callback<OUT> callback);
static <T, R> ChannelFuture<T, R> newPromise(ExecutorService es) {
return new ChannelFutureImpl<>(es);
}
}
ChannelFutureImpl.java
package org.example.async;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChannelFutureImpl<IN, OUT> implements ChannelFuture<IN, OUT> {
private ExecutorService es;
private final static ExecutorService[] _esArray = new ExecutorService[Runtime.getRuntime().availableProcessors()];
static {
for (int i = 0; i < _esArray.length; i++) {
final String threadName = "Processor_" + i;
_esArray[i] = Executors.newSingleThreadExecutor((newRunnable) -> {
Thread newThread = new Thread(newRunnable);
newThread.setName(threadName);
return newThread;
});
}
}
public ChannelFutureImpl(ExecutorService es) {
this.es = es;
}
@Override
public FutureTask addListener(int hashId, Task<IN, OUT> task, IN input, Callback<OUT> callback) {
final FutureTask<OUT> future = new FutureTask<>();
if (hashId < 0) {
hashId = 0;
}
if (hashId >= _esArray.length) {
hashId = _esArray.length - 1;
}
_esArray[hashId].execute(() -> {
// 阻塞的在别的线层等待执行完毕
OUT result = task.get(input);
future.setSuccess(result);
es.execute(() -> {
// 将结果回调过去
if (null != callback) {
callback.call(result);
}
});
});
return future;
}
}
Future.java
package org.example.async;
public interface Future<T>
{
T sync() throws InterruptedException;
}
FutureTask.java
package org.example.async;
public class FutureTask<T> implements Future<T> {
private T result;
private boolean isDone = false;
private final Object LOCK = new Object();
@Override
public T sync() throws InterruptedException {
synchronized (LOCK) {
while (!isDone) {
LOCK.wait();
}
return result;
}
}
protected void setSuccess(T result) {
synchronized (LOCK) {
if (isDone){
return;
}
this.result = result;
this.isDone = true;
LOCK.notifyAll();
}
}
}
Task.java
package async;
public interface Task<IN, OUT>
{
OUT get(IN input);
}
测试
package org.example.async;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
public class FutureTest {
public static void main(String[] args) throws InterruptedException {
// 业务线程
ExecutorService es = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("业务线程");
return t;
}
});
for (int i = 0; i < 10; i++) {
// es作为参数,是为了当异步计算完毕,将回调结果传递到es所在的业务线程
ChannelFuture<String, String> future = ChannelFuture.newPromise(es);
FutureTask promise = future.addListener(i % 5, input -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return input + " World";
}, "Hello" + i, (ret) -> {
System.out.println(ret + ":" + Thread.currentThread().getName());
});
// 加上这行后,就会同步的等待结果
// System.out.println(promise.sync());
}
}
}
/*
Hello3 World:业务线程
Hello0 World:业务线程
Hello2 World:业务线程
Hello1 World:业务线程
Hello5 World:业务线程
Hello6 World:业务线程
Hello7 World:业务线程
Hello4 World:业务线程
Hello8 World:业务线程
Hello9 World:业务线程
*/
总结:
不管是异步还是什么,线程间的同步使用synchronized+wait+notify+notifyAll机制用的不少。
直接new接口,并实现方法就可以搞出来一个匿名类。
异步为了不阻塞调用者线程必然是在别的线程计算,计算完后要回到调用线程。
之所以调用get后阻塞就是因为: 在拿到结果前,wait了,别的线程计算完毕赋值好,通过lock.notify即可拿到结果,这就是线程之间通信的机制。
泛型很好用,这样子写一遍代码,就可以用到所有的数据类型了。
-------------------------------------------20210917------------------------------------------
Worker多线程进行任务计算,并把结果提交到逻辑单线程池,从而在逻辑线程拿到Worker的结果,实现并发安全