首页 > 编程语言 >源码解读之FutureTask如何实现最大等待时间

源码解读之FutureTask如何实现最大等待时间

时间:2023-03-28 14:14:24浏览次数:43  
标签:Thread int COMPLETING state 源码 线程 NEW FutureTask 等待时间

预备知识:Java 线程挂起的常用方式有以下几种

  1. Thread.sleep(long millis):这个方法可以让线程挂起一段时间,并释放 CPU 时间片,等待一段时间后自动恢复执行。这种方式可以用来实现简单的定时器功能,但如果不恰当使用会影响系统性能。
  2. Object.wait()Object.notify()Object.notifyAll():这是一种通过等待某个条件的发生来挂起线程的方式。wait() 方法会让线程等待,直到其他线程调用了 notify()notifyAll() 方法来通知它。这种方式需要使用 synchronized 或者 ReentrantLock 等同步机制来保证线程之间的协作和通信。
  3. LockSupport.park()LockSupport.unpark(Thread thread):这两个方法可以让线程挂起和恢复。park() 方法会使当前线程挂起,直到其他线程调用了 unpark(Thread thread) 方法来唤醒它。这种方式比较灵活,可以根据需要控制线程的挂起和恢复。

一:示例-引入主题

public class FutureTaskDemo {
    public static void main(String[] args) {
        FutureTask<String> 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);
        }
    }

3.1 总体解读awaitDone

利用自旋(for (;

标签:Thread,int,COMPLETING,state,源码,线程,NEW,FutureTask,等待时间
From: https://www.cnblogs.com/jinliang374003909/p/17264944.html

相关文章