Ejecutable
La interfaz Runnable es muy simple, define un método run(), que implementa el método run de la interfaz Runnable para realizar subprocesos múltiples.
// 函数式接口
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Llamable
Mucha gente sabe que para obtener resultados de valor de retorno asíncronos en subprocesos múltiples, generalmente se logra mediante el uso de las interfaces Callable y FutureTask, pero es posible que muchas personas no sepan que Callable se basa en el método de ejecución de Runnable para realizar tareas, y luego pasa FutureTask para recopilar los resultados del valor de retorno, simulemos y escribamos un código FutureTask para ver cómo se implementa.
/**
* @author yinfeng
* @description 自己实现futureTask,基于park/unpark进行线程通讯
* @since 2022/1/9 21:32
*/
public class MyFutureTask<T> implements Runnable {
Callable<T> callable;
/**
* callable执行结果
*/
T result;
/**
* task执行状态
*/
String state = "new";
/**
* 存储正在等待的消费者
*/
LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();
public MyFutureTask(Callable<T> callable) {
this.callable = callable;
}
@Override
public void run() {
try {
result = callable.call();
} catch (Exception e) {
e.printStackTrace();
} finally {
state = "end";
}
// 任务执行完成后通过unpark通知消费者
System.out.println(Thread.currentThread().getName() + " 生产者执行结束,通知消费者");
while (true) {
Thread waiter = waiters.poll();
if (waiter == null) {
break;
}
LockSupport.unpark(waiter);
}
}
/**
* park / unpark
*/
public T get() throws Exception {
Thread mainThread = Thread.currentThread();
// 塞入等待的集合中
waiters.add(mainThread);
// 判断状态
System.out.println(Thread.currentThread().getName() + " 消费者进入等待");
while (!"end".equals(state)) {
// 阻塞等待任务执行完成后通知
LockSupport.park(mainThread);
}
return result;
}
}
Escribamos una demostración para probarlo
/**
* @author yinfeng
* @description
* @since 2022/1/9 21:32
*/
public class FutureTaskTest {
public static void main(String[] args) throws Exception {
final MyFutureTask<String> futureTask = new MyFutureTask<>(() -> {
Thread.sleep(5000);
return "任务完成888";
});
new Thread(futureTask).start();
final String result = futureTask.get();
System.out.println("结果:"+result);
// 控制台打印如下:
// main 消费者进入等待
// Thread-0 生产者执行结束,通知消费者
// 结果:任务完成888
}
}
Puede ver que nuestra demostración también se ejecuta normalmente, por lo que el punto clave es que Callable depende de Runnablecorrermétodo para realizar tareas