Runnable
Runnable接口非常简单,就定义了一个办法run(), 实现Runnable接口的run办法就能够实现多线程
// 函数式接口@FunctionalInterfacepublic interface Runnable { public abstract void run();}
Callable
很多人都晓得要想在多线程中获取异步返回值后果个别是用Callable和FutureTask接口来配合实现,但可能很多人都不晓得其实Callable是依赖于Runnable的run办法进行执行工作的,而后在通过FutureTask来收集返回值后果,上面咱们就本人模仿写一份FutureTask代码来看看是怎么实现的吧。
/** * @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; }}
咱们写个demo测试一下
/** * @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 }}
能够看到咱们的demo也是失常运行的,所以很要害的一点还是Callable是依赖于Runnable的run办法进行执行工作的