iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >FutureTask怎么实现最大等待时间
  • 362
分享到

FutureTask怎么实现最大等待时间

2023-07-05 17:07:48 362人浏览 八月长安
摘要

这篇文章主要介绍了FutureTask怎么实现最大等待时间的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇FutureTask怎么实现最大等待时间文章都会有所收获,下面我们一起来看看吧。预备知识Java 线程挂起

这篇文章主要介绍了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) 方法来唤醒它。这种方式比较灵活,可以根据需要控制线程的挂起和恢复。

先上结论

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

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

示例-引入主题

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);        }    }

总体解读awaitDone

利用自旋(for (;????)的方式 ,检查state(任务状态)与waitNode(维护等待的线程),

首先检查if (Thread.interrupted()) 线程是否被打断(LockSupport.parkNanos挂起的线程被打断不抛出异常),

判断任务状态与waitNode是否入队+确定最大等待时间

若已完成(if (s > COMPLETING))返回任务状态

若已完成(if (s == COMPLETING))-->表示正在完成,但尚未完成。则让出 CPU,进入就绪状态,等待其他线程的执行

若if (q == null)==>创建等待等待节点

若if (!queued)==>表示上一步创建的节点没有和当前线程绑定,故绑定

最后else if (timed)与else,判断最大等待时间

static final class WaitNode {        volatile Thread thread;        volatile WaitNode next;        WaitNode() { thread = Thread.currentThread(); }    }
private static final int NEW          = 0;private static final int COMPLETING   = 1;private static final int NORMAL       = 2;private static final int EXCEPTIONAL  = 3;private static final int CANCELLED    = 4;private static final int INTERRUPTING = 5;private static final int INTERRUPTED  = 6;state可能转换的过程     1.NEW -> COMPLETING -> NORMAL (成功完成)    2.NEW -> COMPLETING -> EXCEPTIONAL (异常)    3.NEW -> CANCELLED (任务被取消)    4.NEW -> INTERRUPTING -> INTERRUPTED(任务被打断)

关键代码

LockSupport.park(this, nanos) ==内部实现==> UNSAFE.park(false, nanos)();

即让当前线程堵塞直至指定的时间(nanos),该方法同Thread.sleep()一样不会释放持有的对象,但不同的是Thread.sleep会被打断(interrupted)并抛出异常,而LockSupport.park被打断不会抛出异常,故在自旋时(for (;????)需判断if (Thread.interrupted())线程是否被打断(手动抛出异常)。

线程运行时state的变化轨迹

新建时利用构造器设置state=NEW

 public FutureTask(Runnable runnable, V result) {     this.callable = Executors.callable(runnable, result);     this.state = NEW;   // 赋值状态 }

线程运行时state可能变化轨迹

public void run() {        ..........防止多次运行stat()方法..............        try {            Callable<V> c = callable;            if (c != null && state == NEW) {                V result;                boolean ran;                try {                    result = c.call();                    ran = true;                } catch (Throwable ex) {                    result = null;                    ran = false;                    setException(ex); //异常轨迹---> 见下分析                }                if (ran)                    set(result); // 正常轨迹--->见下分析            }        } finally {            runner = null;    //----最后结束---防止线程被打断            int s = state;            if (s >= INTERRUPTING)                handlePossibleCancellationInterrupt(s);        }    }

异常轨迹setException(ex)

protected void setException(Throwable t) {    if (UNSAFE.compareAndSwapint(this, stateOffset, NEW, COMPLETING)) {        outcome = t;        UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state        finishCompletion();        //轨迹变化 2.NEW -> COMPLETING -> EXCEPTIONAL (异常)    }    //否则1: 3.NEW -> CANCELLED (任务被取消)    //否则2: 4.NEW -> INTERRUPTING -> INTERRUPTED(任务被打断)}

正常轨迹 set(result);

NEW -> COMPLETING -> NORMAL (成功完成)

关于“FutureTask怎么实现最大等待时间”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“FutureTask怎么实现最大等待时间”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

--结束END--

本文标题: FutureTask怎么实现最大等待时间

本文链接: https://www.lsjlt.com/news/353923.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • FutureTask怎么实现最大等待时间
    这篇文章主要介绍了FutureTask怎么实现最大等待时间的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇FutureTask怎么实现最大等待时间文章都会有所收获,下面我们一起来看看吧。预备知识Java 线程挂起...
    99+
    2023-07-05
  • java怎么设置等待时间
    在Java中,可以使用`Thread.sleep()`方法来设置线程的等待时间,该方法接受一个以毫秒为单位的参数,表示线程需要等待的...
    99+
    2023-10-24
    java
  • php怎么设置超时等待时间
    在使用 PHP 进行开发时,有时需要执行耗时较长的操作,例如网络请求、数据库查询、文件操作等。在这种情况下,PHP 默认的超时时间可能不足以完成这些操作,导致程序出错。为了解决这个问题,我们需要设置 PHP 的超时等待时间。PHP 的超时等...
    99+
    2023-05-14
  • 怎么用vbscript实现修改屏幕保护的等待时间长度
    本篇内容主要讲解“怎么用vbscript实现修改屏幕保护的等待时间长度”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用vbscript实现修改屏幕保护的等待时间长度”吧!问: 嗨,Scrip...
    99+
    2023-06-08
  • 怎么在Javascript中实现异步等待
    本篇文章给大家分享的是有关怎么在Javascript中实现异步等待,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。async/await 是javascript中的一种模式,可使...
    99+
    2023-06-15
  • Python异步怎么使用等待有时间限制协程
    本文小编为大家详细介绍“Python异步怎么使用等待有时间限制协程”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python异步怎么使用等待有时间限制协程”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。我们可以使...
    99+
    2023-07-05
  • css3缓冲和等待效果怎么实现
    这篇文章主要介绍“css3缓冲和等待效果怎么实现”,在日常操作中,相信很多人在css3缓冲和等待效果怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”css3缓冲和等待效...
    99+
    2024-04-02
  • php怎么设置最大超时时间
    在PHP中,可以通过设置php.ini文件中的max_execution_time参数来设置最大超时时间。步骤如下:1. 打开php...
    99+
    2023-08-24
    php
  • Win10怎么设置待机时间?windows10待机时间设置教程
      win10待机时间设置教程来咯~大家可以参考下问进行win10待机设置,有的朋友认为Windows10系统默认的待机时间太短了,该如何设置呢大家请看下文吧。    1、在Win10桌面空位处点击鼠标右键,在...
    99+
    2023-06-08
    Win10 待机 时间 待机时间 windows10 设置 教程
  • 怎么在JavaScript中实现休眠或等待
    这篇文章将为大家详细讲解有关怎么在JavaScript中实现休眠或等待,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。JavaScript有什么特点1、js属于一种解释性脚本语言;2、在绝大多...
    99+
    2023-06-14
  • 怎么修改php最大时间戳
    随着PHP技术的不断发展和普及,越来越多的人开始使用PHP来开发自己的网站。在使用PHP的过程中,我们都知道时间戳在我们的程序中扮演着非常重要的角色。时间戳在我们的代码中可以用来记录日志、计算时间差、显示时间等等。但是,有些时候我们发现程序...
    99+
    2023-05-14
  • SQLServer 错误 847 等待闩锁时出现超时: 类“%ls”,id %p,类型 %d,任务 0x%p : %d,等待时间 %d,标志 0x%I64x,所属任务 0x%p。 将继续等待。 故障
    详细信息 Attribute 值 产品名称 SQL Server 事件 ID 847 事件源 MSSQLSERVER 组件 SQLEngine 符号名称 空值 消息正文 等待闩锁时出现超时: 类“%ls”,...
    99+
    2023-11-04
    故障 标志 错误
  • win7怎么设置待机时间
    这篇文章给大家分享的是有关win7怎么设置待机时间的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。在笔记本Win7系统中,打开控制面板,找到硬件和声音选项,双击打开。在打开硬件和声音选项后,找到电源选项这项,这里要...
    99+
    2023-06-27
  • java中的线程怎么实现等待与通知
    这篇文章给大家介绍java中的线程怎么实现等待与通知,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。关于等待/通知,要记住的关键点是:必须从同步环境内调用wait()、notify()、notifyAll()方法。线程不...
    99+
    2023-05-31
    java 线程 ava
  • Redis怎么实现分布式锁和等待序列
    这篇文章主要介绍了Redis怎么实现分布式锁和等待序列,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在集群下,经常会因为同时处理发生资源争抢...
    99+
    2024-04-02
  • css怎么实现最基本的时间轴
    这篇文章给大家分享的是有关css怎么实现最基本的时间轴的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。原型:代码: <!DOCTYPE html ><html>...
    99+
    2023-06-08
  • 无需等待!PHP 和 Bash 可以实现实时对象处理!
    在现代应用程序开发中,实时对象处理已成为越来越重要的一部分。实时对象处理可以帮助我们在处理大量数据时,快速地对数据进行分析和操作。在本文中,我们将介绍如何使用PHP和Bash实现实时对象处理,以帮助您更好地利用现代应用程序开发中的实时对象...
    99+
    2023-08-14
    bash 对象 实时
  • sql怎么查询最大时间的数据
    要查询最大时间的数据,可以使用以下SQL语句: SELECT * FROM table_name WHERE ti...
    99+
    2024-04-09
    sql
  • mysql怎么设置sql最大执行时间
    在MySQL中,可以通过设置会话级的max_execution_time变量来控制SQL的最大执行时间。 可以通过以下步骤设置SQL...
    99+
    2023-10-24
    sql mysql
  • 数据库的等待事件什么时候会出现
    这篇文章主要介绍“数据库的等待事件什么时候会出现”,在日常操作中,相信很多人在数据库的等待事件什么时候会出现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”数据库的等待事件什么...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作