详解FutureTask如何实现最大等待时间

这篇文章主要为大家详细介绍了如何从源码中了解FutureTask实现最大等待时间的方法,文中的示例代码讲解详细,感兴趣的可以了解一下

预备知识

Java 线程挂起的常用方式有以下几种

Thread.sleep(long millis):这个方法可以让线程挂起一段时间,并释放 CPU 时间片,等待一段时间后自动恢复执行。这种方式可以用来实现简单的定时器功能,但如果不恰当使用会影响系统性能。

Object.wait() 和 Object.notify() 或 Object.notifyAll():这是一种通过等待某个条件的发生来挂起线程的方式。wait() 方法会让线程等待,直到其他线程调用了 notify() 或 notifyAll() 方法来通知它。这种方式需要使用 synchronized 或者 ReentrantLock 等同步机制来保证线程之间的协作和通信。

LockSupport.park() 和 LockSupport.unpark(Thread thread):这两个方法可以让线程挂起和恢复。park() 方法会使当前线程挂起,直到其他线程调用了 unpark(Thread thread) 方法来唤醒它。这种方式比较灵活,可以根据需要控制线程的挂起和恢复。

先上结论

1.futureTask.get时通过LockSupport.park()挂起线程

2.在Thread.run() 方法中 调用 setException(ex)或set(result),然后调用LockSupport.unpark(t)唤醒线程。

示例-引入主题

public class FutureTaskDemo { public static void main(String[] args) { FutureTask futureTask = new FutureTask<>(new Callable() { @Override public Object call() throws Exception { System.out.println("异步线程执行"); Thread.sleep(3000);//模拟线程执行任务需要3秒 return "ok"; } }); Thread t1 = new Thread(futureTask, "线程一"); t1.start(); try { //关键代码 String s = futureTask.get(2, TimeUnit.SECONDS); //最大等待线程2秒 } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } } } 

进入futureTask.get(2, TimeUnit.SECONDS)

  public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { if (unit == null) throw new NullPointerException(); int s = state; if (s <= COMPLETING && (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING) //重点awaitDone,即完成了最大等待,依然没有结果就抛出异常逻辑 throw new TimeoutException(); return report(s); } 

awaitDone返回线程任务执行状态,即小于等于COMPLETING(任务正在运行,等待完成)抛出异常TimeoutException

进入(awaitDone(true, unit.toNanos(timeout)))原理分析

private int awaitDone(boolean timed, long nanos) throws InterruptedException { final long deadline = timed ? System.nanoTime() + nanos : 0L; WaitNode q = null; boolean queued = false; for (;;) { if (Thread.interrupted()) { removeWaiter(q); throw new InterruptedException(); } int s = state; if (s > COMPLETING) { if (q != null) q.thread = null; return s; } else if (s == COMPLETING) // cannot time out yet Thread.yield(); else if (q == null) q = new WaitNode(); else if (!queued) queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q); else if (timed) { nanos = deadline - System.nanoTime(); if (nanos <= 0L) { removeWaiter(q); return state; } LockSupport.parkNanos(this, nanos); } else LockSupport.park(this); } } 

总体解读awaitDone

利用自旋(for (;

以上就是详解FutureTask如何实现最大等待时间的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » Java