您目前所在位置: 首页 > 同类游戏专题 > 魔兽争霸 > 魔兽争霸游戏攻略

魔兽争霸3不能初始化directx_魔兽争霸3不能初始化directx81

时间:2022-02-13 09:23:50 | 访问:102 次 | 责任编辑:访客 | 来源:本站
魔兽争霸3不能初始化directx,魔兽争霸3不能初始化directx81

内容导航:
  • AMD 推出 2152 显卡驱动更新
  • 2019年十大突破技术出炉:比尔·盖茨作序,癌症疫苗上榜
  • 「从入门到放弃Java」并发编程NIOChannel
  • 一、AMD 推出 2152 显卡驱动更新

    IT之家 5 月 19 日消息 AMD 官方今日发布了 Radeon 肾上腺素 21.5.2 驱动更新,为游戏《往日不再》提供了性能优化,并且还增加了对微软 DirectX 12 Agility SDK 和微软 Shader Model 6.6 的支持

    AMD 推出 21.5.2 显卡驱动更新

    IT之家了解到,像往常一样,本次驱动更新还修复了一些错误,修复了《赛博朋克 2077》中启用光线追踪时 Radeon RX 6000 显卡会出现阴影损坏问题,还修复了当使用 Record & Stream 选项卡并且显示器正在被热插拔时,Radeon 驱动程序崩溃的问题。

    AMD 推出 21.5.2 显卡驱动更新

    以下是详细的修复日志:

    • 使用恢复出厂设置选项卸载或升级 Radeon 驱动程序时可能会删除与 Radeon 驱动程序存储在同一目录中的 AMD 芯片组驱动程序文件夹。(建议希望执行恢复出厂设置的用户使用最新的 AMD 清理工具来代替。)

    • 《赛博朋克 2077》中启用光线追踪时 Radeon RX 6000 显卡可能会出现阴影损坏。

    • 在 Radeon RX 5000 系列显卡或更高版本上使用 HEVC 时,AMD Link 在优化过程中会出现间歇性的信号丢失。

    • Radeon 驱动程序下载或启动 Ryzen Master 时,按钮可能会间歇性消失或无法初始化 Ryzen Master。

    • 在 RyzenTM Mobile 4000 系列和 RyzenTM Mobile 5000 系列上,FPS 记录可能不正确或无法记录。

    • 当使用 Record & Stream 选项卡并且显示器被热插拔时,Radeon 驱动程序可能会出现崩溃。

    二、2019年十大突破技术出炉:比尔·盖茨作序,癌症疫苗上榜

    当地时间2月27日,《麻省理工科技评论》正式揭晓2019年“十大突破性技术”(10 Breakthrough Technologies),与往年不同的是,今年《麻省理工科技评论》邀请比尔·盖茨作为客座评选人参与评选,并为榜单作序。

    作为全球新兴科技领域的权威榜单,《麻省理工科技评论》“十大突破性技术”榜已有18年历史。今年上榜的“十大突破性技术”分别是:灵巧机器人、核能新浪潮、早产预测、肠道探测药片、定制癌症疫苗、人造肉汉堡、捕获二氧化碳、可穿戴心电仪、无下水道卫生间和流利对话的 AI 助手。

    “就目前而言,能改变人类的技术创新都既能延长寿命,又能提高生活质量的,我选出的技术也是基于这两个考量”,盖茨在榜单的序言中介绍了他的选择标准。他还表示,他所选出的技术,从预测早产的简单血液测试,到能够消灭致命病原体的厕所,都是未来拯救生命的强大武器。

    他同时为榜单上其他能够改善人们生活的技术感到兴奋,比如穿戴式健康监测设备会给心脏病人预警即将出现的问题,血糖检测仪能帮糖尿病人时刻追踪血糖指标、控制病情发展,先进的核反应堆能为世界提供无碳、安全、可靠的能源,人工智能助理甚至能帮忙人们把电子邮箱都整理好。

    比尔·盖茨认为,“以上的美好生活,就是值得为之奋斗的未来”。

    2019年十大突破技术出炉:比尔·盖茨作序,癌症疫苗上榜

    《麻省理工科技评论》2019年3-4期封面。 MIT Technology Review 官网 图

    展望20 年后的“十大突破性技术”榜单,比尔·盖茨希望上榜的都是以提升人类福祉为目标的技术,例如,探讨人类的幸福感如何提升、人与人之间有意义的连接如何建立、怎样才能帮助每个人都过上充实的生活等。

    据《麻省理工科技评论》编辑Gideon Lichfield介绍,编辑部曾为比尔·盖茨提供20个可供选择的突破性技术,但他几乎全部拒绝了。最终出炉的这份榜单基本由比尔·盖茨自行挑选,代表着奇特而乐观的“盖茨式信念”——“如果说,在过去,大多数技术突破是为了让生命更长久,那么在未来,大多数技术突破是为了让生活更舒适。”

    需要指出的是,上述榜单中的不少技术都与比尔及梅琳达·盖茨基金会的工作或者比尔·盖茨的个人投资有关。对于这些利益冲突,编辑解释称,这种重合性正好能反映在盖茨心目中,哪些技术将会给人类带来最大的福祉,而这也正是他们向比尔·盖茨寻求建议的原因所在。

    2018年上榜的“十大突破性技术”分别是:给所有人的人工智能、对抗性神经网络、人造胚胎、“基因占卜”、传感城市、巴别鱼耳塞、完美的网络隐私、材料的量子飞跃、实用型 3D 金属打印机和零碳排放天然气发电。

    以下是2019年“十大突破性技术”榜单的详细内容:

    1.灵巧机器人

    重大意义:机器正在通过自我学习学会应对这个现实世界。如果机器人能学会应对混乱的现实世界,那么它们就可以胜任更多的任务。

    主要研究者:OpenAI(人工智能非营利组织)、卡内基梅隆大学、密歇根大学、加州大学伯克利分校

    成熟期:3-5年

    尽管人们一直在讨论机器取代人类工作的话题,但目前工业机器人仍然表现得较为笨拙且灵活性欠佳。虽然机器人可以在装配线上不厌其烦地重复着同一个动作,同时还能保持超高的精度,但哪怕目标物体被稍微移动了一点,或将其替换成不同的零件,机器人的抓取过程就会变得十分笨拙甚至是直接抓空。

    现阶段,我们还要取得更多的突破才能让机器人变得更加灵活。但如果研究人员能够很好地利用这种学习方法,未来的机器人将有望能够学会组装电子产品、将餐具摆入洗碗机里、甚至是能够将卧床的人从床上扶起。

    2.核能新浪潮

    重大意义:先进的核聚变和核裂变反应堆正在走进现实。在减少碳排放和限制气候变化的努力方面,核能的作用似乎正变得越来越不可或缺。

    主要研究者:陆地能源(Terrestrial Energy)、泰拉能源(TerraPower)、纽斯凯尔(NuScale)、General Fusion

    成熟期:新型核裂变反应堆到 2020 年代中期有望实现大规模应用;核聚变反应堆仍需至少十年时间。

    在过去的一年中,新型核反应堆发展势头强劲,核能的使用将会变得更安全,成本也更低。新型反应堆的发展包括:颠覆了传统设计的第四代核裂变反应堆、小型模块化反应堆,以及似乎永远也无法实现的核聚变反应堆。

    核聚变方面也有进展。虽然没人指望可控核聚变技术会在 2030 年以前实现交付,但像 General Fusion 和 Commonwealth Fusion Systems 这样的来自麻省理工学院的初创企业,正在取得一些积极进展。(比尔·盖茨是泰拉能源和 Commonwealth Fusion Systems 的投资方。)

    3.早产预测

    重大意义:每年有 1500 万婴儿过早出生,这是 5 岁以下儿童死亡的主要原因、

    主要研究者:Akna Dx

    成熟期:可在 5 年内进入临床测试。

    简单的验血可以预测孕妇是否有过早分娩的风险。我们的遗传物质主要存在于细胞内。但是少量的“无细胞”DNA 和 RNA 也漂浮在我们的血液中,通常由垂死细胞释放。在孕妇中,这些游离的遗传物质碎片来自胎儿、胎盘和母亲的细胞。斯坦福大学的生物工程师 Stephen Quake 已经找到了一种方法来解决医学界最棘手的问题之一:大约十分之一的婴儿过早出生。

    通过对母亲血液中的自由漂浮的 RNA 进行测序,Quake 筛选出与早产有关的七种基因表达的波动。这让他可以识别可能过早分娩的女性。一旦被警告,医生可以采取措施避免早产,并给予孩子更好的生存机会。Quake 说,血液检测所运用的技术,快速,简便,每次测量不到 10 美元。他和他的合作者已经创办了一家创业公司 Akna Dx 将其商业化。

    4.肠道探测药片

    重大意义:一种小型的、可吞咽的设备,不使用麻醉也可以捕捉到肠道的详细图像,甚至在婴儿和儿童体内也可以。这一设备使肠道疾病的探测和研究变得更为容易,其中包括使贫困地区的数百万儿童发育不良的一种疾病。

    主要研究者:麻省总医院(Massachusetts General Hospital)

    成熟期:目前在成人体内使用;婴儿试验将于2019年进行。

    麻省总医院(MGH)的病理学家和工程师 Guillermo Tearney 研发了一种小型设备,这种设备能够检测环境性肠功能障碍(EED)的表现症状,甚至可以进行组织活检。

    与内窥镜不同,它在基础保健检测过程中应用简单。Tearney 的可吞咽胶囊包括缩小版的显微镜。这些显微镜附在可弯曲的线型的系绳上,这些系绳为带有显示器、形似公文包的操纵台发送图片时提供电和光。这使得医疗人员能在有异常的地方暂停,并在结束时将设备拉出来,给它消毒,并重复利用(这听起来有点令人不适,但是 Tearney 的团队已经研发出一种技术,据他们说,这种技术不会造成不适。)它还带有以单细胞分辨率拍摄消化道表面的技术,以及捕捉几毫米深度的三维横截面的技术。

    5.定制癌症疫苗

    重大意义: 通过识别各肿瘤的特异性突变,激发人体的天然防御能力,从而对癌细胞进行针对性破坏。传统化学疗法对健康细胞有很大影响,而且对肿瘤的治疗效果并不总是理想。

    主要研究者:BioNTech 、Genentech

    成熟期:已在临床试验

    目前,科学家正处于将首支个性定制疫苗商业化的关键时刻。如果其效果真如预期的话,该疫苗就的确能够通过肿瘤独特的突变触发人体免疫系统对其进行识别,从而有效地阻止多种癌症的发生。

    更重要的是,与传统化学疗法不同,疫苗是通过使用人体的天然防御系统来选择性地破坏肿瘤细胞的,对健康细胞的损害较有限。此外,在初始治疗后,攻击性免疫细胞将也会对游离的癌细胞保持警惕。

    6.人造肉汉堡

    重大意义:实验室培育的人造肉和植物制成的素肉,能在不破坏环境的情况下接近真实肉类的味道和营养价值。人造肉的出现,可以缓解畜牧业生产造成的毁灭性的森林砍伐、水污染和温室气体排放。

    主要研究者:美国人造肉企业Beyond Meat

    成熟期:目前已经有成形的植物性素肉;2020年左右可研制成功实验室人造肉。

    实验室人造肉的过程,是从动物身上提取肌肉组织,然后放入生物反应器进行培育。虽然最终成品的口感可能有待提高,但外形上已经与我们正常吃的肉差不多了。荷兰马斯特里赫大学的研究人员已在为实验室人造肉的量产而努力。他们认为,到明年,人造肉汉堡的生产成本可能都比牛肉汉堡还低。但人造肉也不完美,生产人造肉对环境到底有多大改善,我们还只能粗估。世界经济论坛最近的一份报告说,生产实验室人造肉的温室气体排放量也只比生产牛肉生产少大概 7%。

    7.捕获二氧化碳

    重大意义:实用且经济地从空气中直接捕获二氧化碳的方法,可以吸走超量排放的温室气体。从大气中去除CO2可能是阻止灾难性的气候变化最后的可行方法之一。、

    主要研究者:Carbon Engineering、Climeworks、Global Thermostat

    成熟期:5到10年

    去年夏天,哈佛大学气候科学家大卫·凯斯(David Keith)计算之后惊喜地发现,一种叫做直接空气捕获(Direct Air Capture,DAC)的方法,理论上可以将机器捕集二氧化碳的成本降低到每吨 100 美元以下。先前估计的成本要比这个数字高出一个数量级,因而许多科学家曾认为这项技术太过昂贵,不具备可行性。不过,直接空气捕获仍需至少数年的时间,才有可能将成本降低到接近 100 美元的范围。

    8.可穿戴心电仪

    重大意义: 随着监管机构的批准和相关技术的进步,人们可以轻松通过可穿戴设备持续监测自己的心脏健康。可检测心电图的智能手表可以预警如心房颤动等潜在的危及生命的心脏疾病。

    主要研究者:苹果、AliveCor、Withings

    成熟期:现在

    随着监管部门新法规的出台和软、硬件的相关创新,心电监测智能手表已经问世,它具有可穿戴设备的便利性,并且能够提供接近医疗设备的精度。硅谷初创公司 AliveCor 推出了一款与苹果手表兼容的腕带,该腕带可以检测出心房颤动,这是导致血栓和中风的常见原因。

    现阶段的可穿戴心电图监测设备仍然只有一个传感器,而真正的心电图设备则有 12 个传感器。目前还没有任何一种可穿戴设备能够诊断心脏病。

    9.无下水道卫生间

    重大意义: 节能厕所可以在没有下水道系统的情况下使用,并且可以就地分解粪便。23亿人缺乏安全的卫生设施,并许多人因此死亡。

    主要研究者:杜克大学、南佛罗里达大学、Biomass Controls、加州理工学院

    成熟期:1-2年

    现在,研究人员正在努力开发一种新型厕所,这种厕所对发展中国家来说也足够便宜,不仅可以处理粪便,还可以对其进行分解。

    2011 年,比尔·盖茨提出重新发明厕所挑战,并设立了 X 大奖。自从挑战开始以来,有几个团队已经将设计的厕所原型投入使用。所有的粪便都是就地处理的,不需要用大量的水把它们送到遥远的处理厂。

    10.流利对话的 AI 助手

    重大意义:捕捉单词之间语义关系的新技术正在使机器更好地理解自然语言。人工智能助手现在可以执行基于对话的任务,如预订餐厅或协调行李托运,而不仅仅是服从简单命令。

    主要研究者:谷歌、阿里巴巴、亚马逊

    成熟期:1-2 年后

    我们已经习惯了人工智能助手——Alexa 在客厅里播放音乐,Siri 在你的手机上为你定闹钟——但它们并没有真正做到所谓的智能。它们本应简化我们的生活,但却收效甚微。它们只识别很小范围的指令,稍遇偏差就很容易出错。

    尽管人工智能程序能更好地找出你的需求,它们仍然不能理解一个完整的句子。脚本化或由统计生成的回答反映了向机器灌输真正的语言理解是多么困难。一旦我们解决了这个难题,我们也许会看到人工智能的另一种进化:从物流协调员到保姆、老师,甚至朋友。

    比尔·盖茨为2019年“十大突破性技术”榜单所写的序言:

    世界未来,尽在吾辈手中

    比尔·盖茨

    能受邀成为到《麻省理工科技评论》2019年度“十大突破性技术”的首位客座评选人,我倍感荣幸。从众多科技成果中优中选优并不容易。因为我希望我参与选出的技术,不仅是 2019 年的关注焦点,更能为整个科技史留下浓重的一笔。这也令我思考,科技创新是如何随着时间的推移而演变的。

    说到改变世界的突破性技术,我第一个想到的,是犁。它完美代表了人类创新的历史。早在公元前 4000 年,美索不达米亚的农民们就开始用磨尖了的棍子给土壤透气。后来,经历了漫长的修补和完善,我们终于看到了今天的犁,这一技术上的奇迹。

    但犁到底有什么用呢?犁,能用来创造:有了犁,我们能播撒更多种子,收获更多粮食,有更多东西吃。可以毫不夸张地说,在那些缺乏食物的地方,犁就是人们多活几年的保障。与古代、现代的很多技术一样,犁能以更有效的方式创造更多东西,也让更多人受益。

    实验室人造肉类是我今年选出的十大突破性技术之一。与犁相比,在实验室里培养动物蛋白并不是为了养活更多人。即便肉类需求上升,现在的家畜也已足够养活全世界了。下一代蛋白质不是为了让肉更多,而是为了让肉更好。它让我们在不助长森林砍伐或甲烷排放的前提下,更好地供给这个人口不断增长、生活水平不断提升的世界,让我们不用杀害任何动物就能享用汉堡。

    换句话说,犁延长了我们的寿命,而实验室中制造的肉类则改善了我们的生活质量。人类历史中,我们的大部分创新都给了前者,我们的努力也取得了回报:全球人口预期寿命从 1913 年的 34 岁,1973 年的 60 岁,提高到了今天的 71 岁。随着寿命的延长,我们的注意力也慢慢转向生活幸福感的提升。如果我们把突破性技术分为增加物质满足和提升生活质量两类,你可能会觉得 2009 年的榜单好像和今年的没什么不同。因为人们关注点的改变和大多数进步一样,非常渐进,难以察觉。整个过程需要几十年而不是几年 - 我相信,我们只是还在转型的过程中。

    还要明确一件事,我认为人类短期内不会放弃对延长寿命的探索。我们离人人都能健康长寿这个目标还很遥远,还要做出大量的创新。此外,我刚提到的“质”和“量”可以同时提升。举例来说,有了疟疾疫苗,儿童不再会因为疟疾而发育迟缓,这是对孩子生命的拯救,也是对他们生活质量的提升。

    放在历史的长河里看,我们对时下的世界如此着迷,就是因为现在,增加物质满足和提升生活质量可以一起实现。如果要我预测一下这个榜单几年后的评选结果,我敢打赌,治疗慢性病的技术将会是一大主题,我说的技术并不光是新的药物(虽然我个人很想看到阿尔茨海默症等疾病的新药上榜),还有能帮关节炎患者保持灵活的机械手套,能帮重度抑郁患者得到所需治疗的手机应用之类的创新。

    如果把眼光放得再远一些,比如展望一下 20 年后的技术榜单,我希望上榜的几乎都是以提升人类福祉为目标的技术。我认为未来的聪明人会关注更加形而上学的问题,比如说:人类的幸福感如何提升?人与人之间有意义的连接如何建立?怎样才能帮助每个人都过上充实的生活?

    我很愿意看到 2039 年的榜单是围绕着这些问题展开的,因为这意味着那时的我们已经成功战胜了疾病,还能应对气候变化。这就是在我看来人类能取得的最大的进步。不过,就目前而言,能改变人类的技术创新都既能延长寿命,又能提高生活质量的,我选出的技术也是基于这两个考量。这些技术从不同方面激励我乐观面对未来,希望它们也能对你有所启发。

    我所选出的技术,从预测早产的简单血液测试,到能够消灭致命病原体的厕所,都是未来拯救生命的强大武器。我也为榜单上其他能够改善我们生活的技术感到兴奋,比如穿戴式健康监测设备,其中腕部心电仪会给心脏病人预警即将出现的问题,血糖检测仪能帮糖尿病人时刻追踪血糖指标,控制病情发展;先进的核反应堆能为世界提供无碳、安全、可靠的能源。

    我选出的技术中,还有一项甚至让我们看到,未来的世界将会以实现个人价值为主要目标——它就是属于每个人的人工智能助理,它甚至能帮你把电子邮箱都整理好。

    这听起来可能没什么了不起,但是,当以往每天用来看电子邮件的 30 分钟可以用来做别的,就给生命创造了很多其他可能性。我知道,有些人会用这些时间做更多工作,但我希望大多数人能在这段时间里和朋友喝喝咖啡,辅导一下孩子的功课,甚至是在社区里做做志愿者。

    我想,以上的美好生活,就是值得为之奋斗的未来。

    三、「从入门到放弃Java」并发编程NIOChannel

    前言

    上篇[【从入门到放弃-Java】并发编程-NIO使用]()简单介绍了nio的基础使用,本篇将深入源码分析nio中channel的实现。

    简介

    channel即通道,可以用来读、写数据,它是全双工的可以同时用来读写操作。这也是它与stream流的最大区别。

    channel需要与buffer配合使用,channel通道的一端是buffer,一端是数据源实体,如文件、socket等。在nio中,通过channel的不同实现来处理 不同实体与数据buffer中的数据传输。

    channel接口:

    package ;import on;import ;/** * A nexus for I/O operations. * * <p> A channel represents an open connection to an entity such as a hardware * device, a file, a network socket, or a program component that is capable of * performing one or more distinct I/O operations, for example reading or * writing. * * <p> A channel is either open or closed. A channel is open upon creation, * and once closed it remains closed. Once a channel is closed, any attempt to * invoke an I/O operation upon it will cause a {@link ClosedChannelException} * to be thrown. Whether or not a channel is open may be tested by invoking * its {@link #isOpen isOpen} method. * * <p> Channels are, in general, intended to be safe for multithreaded access * as described in the specifications of the interfaces and classes that extend * and implement this interface. * * * @author Mark Reinhold * @author JSR-51 Expert Group * @since 1.4 */public interface Channel extends Closeable { /** * Tells whether or not this channel is open. * * @return <tt>true</tt> if, and only if, this channel is open */ public boolean isOpen(); /** * Closes this channel. * * <p> After a channel is closed, any further attempt to invoke I/O * operations upon it will cause a {@link ClosedChannelException} to be * thrown. * * <p> If this channel is already closed then invoking this method has no * effect. * * <p> This method may be invoked at any time. If some other thread has * already invoked it, however, then another invocation will block until * the first invocation is complete, after which it will return without * effect. </p> * * @throws IOException If an I/O error occurs */ public void close() throws IOException;}

    常见的channel实现有:

    • FileChannel:文件读写数据通道
    • SocketChannel:TCP读写网络数据通道
    • ServerSocketChannel:服务端网络数据读写通道,可以监听TCP连接。对每一个新进来的连接都会创建一个SocketChannel。
    • DatagramChannel:UDP读写网络数据通道

    FileChannel

    「从入门到放弃-Java」并发编程-NIO-Channel

    「从入门到放弃-Java」并发编程-NIO-Channel

    FileChannel是一个抽象类,它继承了AbstractInterruptibleChannel类,并实现了 SeekableByteChannel, GatheringByteChannel, ScatteringByteChannel接口。

    具体的实现类主要是elImpl。下面详细分析下FileChannelImpl中每个方法的具体实现。

    open

    private FileChannelImpl(FileDescriptor var1, String var2, boolean var3, boolean var4, boolean var5, Object var6) { //主要记载操作系统维护的文件描述符  = var1;  //是否可读  = var3;  //是否可写  = var4;  //是否以追加的方式打开  = var5;   = var6;  = var2;  //底层使用native的read和write来处理文件的  = new FileDispatcherImpl(var5);}//FileInputStream::getChannel 调用 (fd, path, true, false, this) 获取只读channelpublic static FileChannel open(FileDescriptor var0, String var1, boolean var2, boolean var3, Object var4) { return new FileChannelImpl(var0, var1, var2, var3, false, var4);}//FileOutputStream::getChannel 调用 (fd, path, false, true, append, this) 获取只写channelpublic static FileChannel open(FileDescriptor var0, String var1, boolean var2, boolean var3, boolean var4, Object var5) { return new FileChannelImpl(var0, var1, var2, var3, var4, var5);}private FileChannelImpl(FileDescriptor fd, String path, boolean readable, boolean writable, boolean direct, Object parent){  = fd;  //是否可读  = readable;  //是否可写  = writable;  //对于从流创建的channel,在结束时要做不同的清理动作,(openJDK中才有,sun的jdk中没有)  = parent;  //源文件的path  = path;  //是否使用DirectIO  = direct;   = new FileDispatcherImpl(); if (direct) { assert path != null;  = IO(fd, path); } else {  = -1; } //当parent不存在时,则注册一个cleaner,否则交由parent做清理动作。 // Register a cleaning action if and only if there is no parent // as the parent will take care of closing the file descriptor. // FileChannel is used by the LambdaMetaFactory so a lambda cannot // be used here hence we use a nested class instead.  = parent != null ? null : ().register(this, new Closer(fd));}// Used by l(), l// and l()public static FileChannel open(FileDescriptor fd, String path, boolean readable, boolean writable, boolean direct, Object parent){ return new FileChannelImpl(fd, path, readable, writable, direct, parent);}
    • open方法主要是返回一个新new的FileChannelImpl对象,初始化时设置fileDescriptor、readable、writable、append、parent、path等属性,看变量名很容易理解,在此不赘述变量含义。

    read

    //实现自SeekableByteChannel接口的方法,将文件中的内容读取到给定的byteBuffer中public int read(ByteBuffer dst) throws IOException { //保证读写时,channel处于开启状态 ensureOpen();  //判断是否可读 if (!readable) throw new NonReadableChannelException(); synchronized (positionLock) { if (direct) nelPositionAligned(position(), alignment); int n = 0; int ti = -1; try {  //开始阻塞,并注册为Interruptible,可以被中断 beginBlocking();  //将当前线程添加到NativeThreadSet中,并返回索引,方便后续操作。 //NativeThreadSet是一个线程安全的本地线程集合,方便管理,用来发送信号 ti = (); if (!isOpen()) return 0; do { //当未被系统中断(即读取完毕)或channel未被关闭,则一直读,将内容写入到byteBuffer(dst)中 n = (fd, dst, -1, direct, alignment, nd); } while ((n == ED) && isOpen()); return (n); } finally { //把当前线程从set中移出 (ti);  //结束,释放锁 endBlocking(n > 0); assert (n); } }}//实现自ScatteringByteChannel接口的方法,将文件中的内容依次读取到给定的byteBuffer数组中。public long read(ByteBuffer[] dsts, int offset, int length) throws IOException{ if ((offset < 0) || (length < 0) || (offset >  - length)) throw new IndexOutOfBoundsException(); //保证读写时,channel处于开启状态 ensureOpen();  //判断是否可读 if (!readable) throw new NonReadableChannelException(); synchronized (positionLock) { if (direct) nelPositionAligned(position(), alignment); long n = 0; int ti = -1; try { //开始阻塞,并注册为Interruptible,可以被中断 beginBlocking();  //将当前线程添加到NativeThreadSet中,并返回索引,方便后续操作。 //NativeThreadSet是一个线程安全的本地线程集合,方便管理,用来发送信号 ti = (); if (!isOpen()) return 0; do { //当未被系统中断(即读取完毕)或channel未被关闭,则一直读,将内容写入到byteBuffer(dst)中 n = (fd, dsts, offset, length, direct, alignment, nd); } while ((n == ED) && isOpen()); return (n); } finally { //把当前线程从set中移出 (ti);  //结束,释放锁 endBlocking(n > 0); assert (n); } }}

    write

    //实现自SeekableByteChannel接口的方法,将byteBuffer中的内容写入到文件中public int write(ByteBuffer src) throws IOException { //保证写时,channel处于开启状态 ensureOpen();  //判断是否可写 if (!writable) throw new NonWritableChannelException(); synchronized (positionLock) { if (direct) nelPositionAligned(position(), alignment); int n = 0; int ti = -1; try { //开始阻塞,并注册为Interruptible,可以被中断 beginBlocking();  //将当前线程添加到NativeThreadSet中,并返回索引,方便后续操作。 //NativeThreadSet是一个线程安全的本地线程集合,方便管理,用来发送信号 ti = (); if (!isOpen()) return 0; do { //当未被系统中断(即写入完毕)或channel未被关闭,则一直写,将内容写入到文件中 n = (fd, src, -1, direct, alignment, nd); } while ((n == ED) && isOpen()); return (n); } finally { //把当前线程从set中移出 (ti);  //结束,释放锁 assert (n); } }}//实现自GatheringByteChannel接口的方法,将byteBuffer数组中的内容依次写入到文件中public long write(ByteBuffer[] srcs, int offset, int length) throws IOException{ if ((offset < 0) || (length < 0) || (offset >  - length)) throw new IndexOutOfBoundsException(); //保证写时,channel处于开启状态 ensureOpen();  //判断是否可写 if (!writable) throw new NonWritableChannelException(); synchronized (positionLock) { if (direct) nelPositionAligned(position(), alignment); long n = 0; int ti = -1; try { //开始阻塞,并注册为Interruptible,可以被中断 beginBlocking();  //将当前线程添加到NativeThreadSet中,并返回索引,方便后续操作。 //NativeThreadSet是一个线程安全的本地线程集合,方便管理,用来发送信号 ti = (); if (!isOpen()) return 0; do { //当未被系统中断(即写入完毕)或channel未被关闭,则一直写,将内容写入到文件中 n = (fd, srcs, offset, length, direct, alignment, nd); } while ((n == ED) && isOpen()); return (n); } finally { //把当前线程从set中移出 (ti);  //结束,释放锁 assert (n); } }}

    position

    //实现自SeekableByteChannel接口的方法,获取当前channel的positionpublic long position() throws IOException { ensureOpen(); synchronized (positionLock) { long p = -1; int ti = -1; try { beginBlocking(); ti = (); if (!isOpen()) return 0; boolean append = (fd); do { //append模式下,position在channel的末尾 // in append-mode then position is advanced to end before writing p = (append) ? (fd) : (fd, -1); } while ((p == ED) && isOpen()); return (p); } finally { (ti); endBlocking(p > -1); assert (p); } }}//实现自SeekableByteChannel接口的方法,设置当前channel的position为newPositionpublic FileChannel position(long newPosition) throws IOException { ensureOpen(); if (newPosition < 0) throw new IllegalArgumentException(); synchronized (positionLock) { long p = -1; int ti = -1; try { beginBlocking(); ti = (); if (!isOpen()) return null; do { //设置当前position为newPosition p = (fd, newPosition); } while ((p == ED) && isOpen()); return this; } finally { (ti); endBlocking(p > -1); assert (p); } }}

    size

    实现自SeekableByteChannel接口的方法,返回当前实体(文件)的大小

    truncate

    实现自SeekableByteChannel接口的方法,用来截取文件至newSize大小

    force

    实现自SeekableByteChannel接口的方法,用来将channel中尚未写入磁盘的数据强制落盘

    transferTo

    将fileChannel中的数据传递至另一个channel

    transferFrom

    从其它channel读取数据至fileChannel

    SocketChannel

    「从入门到放弃-Java」并发编程-NIO-Channel

    「从入门到放弃-Java」并发编程-NIO-Channel

    open

    /** * Opens a socket channel. * * <p> The new channel is created by invoking the {@link * rovider#openSocketChannel * openSocketChannel} method of the system-wide default {@link * rovider} object. </p> * * @return A new socket channel * * @throws IOException * If an I/O error occurs */public static SocketChannel open() throws IOException { return ().openSocketChannel();}

    open方法是调用SelectorProvider中实现了rovider#openSocketChannel的方法,底层实际是new SocketChannelImpl,调用native方法创建socket

    connect

    public boolean connect(SocketAddress sa) throws IOException { //校验Address是否合法 InetSocketAddress isa = ess(sa);  //获取系统安全管理器 SecurityManager sm = tyManager(); if (sm != null)  //校验IP和端口是否被允许连接 ect(s().getHostAddress(), ()); InetAddress ia = s();  //如果是本机地址,则获取本机的host if (lAddress()) ia = ost(); try { //加读锁 (); try { //加写锁 (); try { int n = 0;  //是否阻塞 boolean blocking = isBlocking(); try { //开启connect前的校验并设置为ST_CONNECTIONPENDING,如果blocking是true 即阻塞模式,则记录当前线程的ID,以便接收信号处理。 beginConnect(blocking, isa); do { //调用native connect方法 n = (fd, ia, ()); } while (n == ED && isOpen()); } finally { //结束连接 endConnect(blocking, (n > 0)); } assert (n); return n > 0; } finally { //释放写锁 (); } } finally { //释放读锁 (); } } catch (IOException ioe) { // connect failed, close the channel close(); throw (ioe, isa); }}

    configureBlocking

    实现自SelectableChannel的接口方法,调用native方法设置socket的阻塞状态

    register

    在AbstractSelectableChannel中定义,注册要监听的事件。

    public final SelectionKey register(Selector sel, int ops, Object att) throws ClosedChannelException{ if ((ops & ~validOps()) != 0) throw new IllegalArgumentException(); if (!isOpen()) throw new ClosedChannelException(); synchronized (regLock) { if (isBlocking()) throw new IllegalBlockingModeException(); synchronized (keyLock) { // re-check if channel has been closed if (!isOpen()) throw new ClosedChannelException(); SelectionKey k = findKey(sel); if (k != null) { (att); ps(ops); } else { // 向Selector中注册事件 // New registration k = ((AbstractSelector)sel).register(this, ops, att); addKey(k); } return k; } }}

    read

    //实现自ReadableByteChannel接口的方法,从socket中读取数据至ByteBuffer@Overridepublic int read(ByteBuffer buf) throws IOException { nNull(buf); (); try { boolean blocking = isBlocking(); int n = 0; try { //检查channel是否开启并已经是connected的状态。如果blocking是true 即阻塞模式,则记录当前线程的ID,以便接收信号处理。 beginRead(blocking); // check if input is shutdown if (isInputClosed) return ; //如果是阻塞模式,则一直读取直到数据读取完毕;非阻塞模式则直接调用native方法不需要等待。 if (blocking) { do { n = (fd, buf, -1, nd); } while (n == ED && isOpen()); } else { n = (fd, buf, -1, nd); } } finally { endRead(blocking, n > 0); if (n <= 0 && isInputClosed) return ; } return (n); } finally { (); }}//实现自ScatteringByteChannel接口的方法,从socket中依次读取数据至ByteBuffer数组@Overridepublic long read(ByteBuffer[] dsts, int offset, int length) throws IOException{ IndexSize(offset, length, ); (); try { boolean blocking = isBlocking(); long n = 0; try { beginRead(blocking); // check if input is shutdown if (isInputClosed) return ; //如果是阻塞模式,则一直读取直到数据读取完毕;非阻塞模式则直接调用native方法不需要等待。 if (blocking) { do { n = (fd, dsts, offset, length, nd); } while (n == ED && isOpen()); } else { n = (fd, dsts, offset, length, nd); } } finally { endRead(blocking, n > 0); if (n <= 0 && isInputClosed) return ; } return (n); } finally { (); }}

    write

    //实现自ReadableByteChannel接口的方法,将ByteBuffer中的数据写入socket@Overridepublic int write(ByteBuffer buf) throws IOException { nNull(buf); (); try { boolean blocking = isBlocking(); int n = 0; try { beginWrite(blocking); //如果是阻塞模式,则一直读取直到数据读取完毕;非阻塞模式则直接调用native方法不需要等待。 if (blocking) { do { n = (fd, buf, -1, nd); } while (n == ED && isOpen()); } else { n = (fd, buf, -1, nd); } } finally { endWrite(blocking, n > 0); if (n <= 0 && isOutputClosed) throw new AsynchronousCloseException(); } return (n); } finally { (); }}@Overridepublic long write(ByteBuffer[] srcs, int offset, int length) throws IOException{ IndexSize(offset, length, ); (); try { boolean blocking = isBlocking(); long n = 0; try { beginWrite(blocking); //如果是阻塞模式,则一直等待直到数据写入完毕;非阻塞模式则直接调用native方法不需要等待。 if (blocking) { do { n = (fd, srcs, offset, length, nd); } while (n == ED && isOpen()); } else { n = (fd, srcs, offset, length, nd); } } finally { endWrite(blocking, n > 0); if (n <= 0 && isOutputClosed) throw new AsynchronousCloseException(); } return (n); } finally { (); }}//实现自ReadableByteChannel接口的方法,将ByteBuffer数组中的数据依次写入socket/** * Writes a byte of out of band data. */int sendOutOfBandData(byte b) throws IOException { (); try { boolean blocking = isBlocking(); int n = 0; try { beginWrite(blocking); //如果是阻塞模式,则一直等待直到数据写入完毕;非阻塞模式则直接调用native方法不需要等待。 if (blocking) { do { n = sendOutOfBandData(fd, b); } while (n == ED && isOpen()); } else { n = sendOutOfBandData(fd, b); } } finally { endWrite(blocking, n > 0); if (n <= 0 && isOutputClosed) throw new AsynchronousCloseException(); } return (n); } finally { (); }}

    ServerSocketChannel

    「从入门到放弃-Java」并发编程-NIO-Channel

    「从入门到放弃-Java」并发编程-NIO-Channel

    socket

    @Overridepublic ServerSocket socket() { synchronized (stateLock) { if (socket == null) socket = (this); return socket; }}

    bind

    @Overridepublic ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException { synchronized (stateLock) { ensureOpen(); if (localAddress != null) throw new AlreadyBoundException(); InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : ess(local); SecurityManager sm = tyManager(); if (sm != null) en(());  //绑定前做一些前置处理,如将tcp socket文件描述符转换成SDP Bind(fd, s(), ());  //绑定IP和地址 (fd, s(), ());  //开始监听,设置socket上最多可以挂起backlog个连接,若backlog小于1 则默认设置50个 (fd, backlog < 1 ? 50 : backlog);  localAddress = ess(fd); } return this;}

    accept

    @Overridepublic SocketChannel accept() throws IOException { (); try { int n = 0; FileDescriptor newfd = new FileDescriptor(); InetSocketAddress[] isaa = new InetSocketAddress[1]; boolean blocking = isBlocking(); try { begin(blocking); do { //阻塞等待接收客户端链接 n = accept(, newfd, isaa); } while (n == ED && isOpen()); } finally { end(blocking, n > 0); assert (n); } if (n < 1) return null; //新接收的socket初始设置为阻塞模式(因此非阻塞模式的每次需要显示设置) // newly accepted socket is initially in blocking mode Blocking(newfd, true); InetSocketAddress isa = isaa[0];  //用新接收的socket创建SocketChannel SocketChannel sc = new SocketChannelImpl(provider(), newfd, isa); // check permitted to accept connections from the remote address SecurityManager sm = tyManager(); if (sm != null) { try { pt(s().getHostAddress(), ()); } catch (SecurityException x) { (); throw x; } } return sc; } finally { (); }}

    ServerSocketChannel并没有read和write方法,只是继承了AbstractSelectableChannel,以便在selector中使用

    DatagramChannel

    「从入门到放弃-Java」并发编程-NIO-Channel

    「从入门到放弃-Java」并发编程-NIO-Channel

    open

    public DatagramChannelImpl(SelectorProvider sp) throws IOException{ super(sp); Create(); try { //如果不支持IPv6则使用IPv4  = 6Available() ? 6 : ;  //设置非流式的socket(tcp是流模式协议,udp是数据报模式协议)  = (family, false);  = (fd); } catch (IOException ioe) { lose(); throw ioe; }}

    receive

    public SocketAddress receive(ByteBuffer dst) throws IOException { if (y()) throw new IllegalArgumentException("Read-only buffer"); (); try { boolean blocking = isBlocking(); int n = 0; ByteBuffer bb = null; try { SocketAddress remote = beginRead(blocking, false); boolean connected = (remote != null); SecurityManager sm = tyManager(); if (connected || (sm == null)) { // connected or no security manager do { n = receive(fd, dst, connected); } while ((n == ED) && isOpen()); if (n == LE) return null; } else { // Cannot receive into user's buffer when running with a // security manager and not connected bb = aryDirectBuffer(()); for (;;) { do { n = receive(fd, bb, connected); } while ((n == ED) && isOpen()); if (n == LE) return null; InetSocketAddress isa = (InetSocketAddress)sender; try { pt(s().getHostAddress(), ()); } catch (SecurityException se) { // Ignore packet (); n = 0; continue; } (); (bb); break; } }  //sender:发送方地址, Set by receive0 (## ugh) assert sender != null; return sender; } finally { if (bb != null) mporaryDirectBuffer(bb); endRead(blocking, n > 0); assert (n); } } finally { (); }}

    send

    public int send(ByteBuffer src, SocketAddress target) throws IOException{ nNull(src); InetSocketAddress isa = ess(target, family); (); try { boolean blocking = isBlocking(); int n = 0; try { //当connect后,remote会设置为连接的地址 SocketAddress remote = beginWrite(blocking, false); if (remote != null) { // connected if (!(remote)) { throw new AlreadyConnectedException(); } do { n = (fd, src, -1, nd); } while ((n == ED) && isOpen()); } else { // not connected SecurityManager sm = tyManager(); if (sm != null) { InetAddress ia = s(); if (stAddress()) { icast(ia); } else { ect(dress(), ()); } } do { n = send(fd, src, isa); } while ((n == ED) && isOpen()); } } finally { endWrite(blocking, n > 0); assert (n); } return (n); } finally { (); }}

    connect

    @Overridepublic DatagramChannel connect(SocketAddress sa) throws IOException { InetSocketAddress isa = ess(sa, family); SecurityManager sm = tyManager(); if (sm != null) { InetAddress ia = s(); if (stAddress()) { icast(ia); } else { ect(dress(), ()); pt(dress(), ()); } } (); try { (); try { synchronized (stateLock) { ensureOpen(); if (state == ST_CONNECTED) throw new AlreadyConnectedException(); int n = (family, fd, s(), ()); if (n <= 0) throw new Error(); // Can't happen // connected remoteAddress = isa; state = ST_CONNECTED; // refresh local address localAddress = ess(fd); // flush any packets already received. boolean blocking = isBlocking(); if (blocking) { Blocking(fd, false); } try { ByteBuffer buf = (100); while (receive(buf) != null) { (); } } finally { if (blocking) { Blocking(fd, true); } } } } finally { (); } } finally { (); } return this;}

    udp是数据报模式的协议,是没有connect的。这里的connect实际上是在底层忽略了与其他地址的数据传输。

    在connect后,就可以像socketChannel似得使用read和write了

    总结

    本文学习了各种channel的实现,主要是对底层native方法的一些封装,针对不同属性的实体(文件、socket),使用对应的channel与byteBuffer传输数据。再通过byteBuffer与byte数据进行转换。

    channel的实现中,封装了大量的native方法,重要的底层实现全在native中,后续可以深入学习下。

    本文中出现的byteBuffer和selector将在接下来的文章中,单独分析。

    作者:aloof_

    本类TOP10
    最新内容
    金融习题 考研百科