当前位置: 首页 > news >正文

Java线程的异常处理:确保线程安全运行

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在上一期文章中,我们探讨了Java线程间的协作与竞争,详细介绍了wait()notify()和线程调度的机制。然而,实际的多线程开发中,一个更为常见的问题是如何在多线程环境下处理异常。线程执行过程中遇到的未处理异常可能会导致应用程序出现不可预期的行为,甚至崩溃。因此,理解Java线程中的异常处理机制是保障程序稳健运行的重要步骤。

本期内容将深入探讨如何在Java中安全处理线程的异常情况,确保多线程程序的健壮性和可维护性。

摘要

Java的多线程编程提供了强大的并发处理能力,但在此过程中处理异常往往容易被忽视。由于线程是独立的执行单元,一旦某个线程发生异常,可能不会立即影响主线程或其他线程的执行。因此,掌握如何捕获并处理线程异常是保障并发程序安全和可靠的重要技能。

本文将从线程异常处理的原理入手,分析常见的错误场景,介绍几种有效的异常处理方法,并通过实际代码演示如何确保线程安全运行。

概述

Java提供了丰富的多线程支持,通常通过实现Runnable接口或继承Thread类来创建并启动线程。然而,在并发环境中,线程中的异常不会被默认传播到主线程,因而导致的错误可能较难发现。我们需要通过特定的机制来捕获线程中的异常,从而保证系统的稳健性。

本篇将涵盖以下内容:

  1. 线程异常的常见问题
  2. Thread.UncaughtExceptionHandler机制的使用
  3. 如何在线程池中处理异常
  4. 实战代码演示:确保线程的异常处理

源码解析

1. 常见的线程异常问题

当线程在运行过程中抛出未捕获的异常时,它不会影响其他线程或主线程的运行。但它可能导致该线程意外终止,影响并发任务的完成。例如:

public class SimpleThreadExceptionDemo {public static void main(String[] args) {Thread thread = new Thread(() -> {throw new RuntimeException("Thread exception!");});thread.start();System.out.println("Main thread is running");}
}

在这个例子中,RuntimeException在子线程中被抛出,而主线程仍然继续运行,输出“Main thread is running”。这个异常没有被任何地方捕获,也不会传递给主线程,这种情况在实际开发中容易被忽视。

2. 使用Thread.UncaughtExceptionHandler处理线程异常

为了解决这种问题,Java提供了Thread.UncaughtExceptionHandler接口,用于处理线程中未捕获的异常。

public class ThreadExceptionHandlerDemo {public static void main(String[] args) {Thread thread = new Thread(() -> {throw new RuntimeException("Thread exception!");});thread.setUncaughtExceptionHandler((t, e) -> {System.out.println("Exception in thread: " + t.getName() + ", Error: " + e.getMessage());});thread.start();}
}

在这个例子中,我们为线程设置了一个UncaughtExceptionHandler,一旦线程抛出未捕获的异常,它将捕获该异常并处理。

3. 在线程池中处理异常

在线程池(如ExecutorService)中,异常处理的机制稍有不同。线程池中的任务通常不会主动传播异常,除非我们通过某种方式捕获并处理它们。可以使用Future来获取任务的执行结果,并通过捕获其抛出的异常来处理:

import java.util.concurrent.*;public class ThreadPoolExceptionDemo {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(2);Future<?> future = executor.submit(() -> {throw new RuntimeException("Task exception!");});try {future.get(); // 这里捕获异常} catch (InterruptedException | ExecutionException e) {System.out.println("Caught exception: " + e.getCause());}executor.shutdown();}
}

通过Future.get()方法,可以捕获线程池中任务抛出的异常,并处理异常逻辑。

使用案例分享

实际案例:文件处理的多线程任务

假设我们有一个文件处理任务,需要处理大量文件,而每个文件的处理可能因为IO异常或文件格式问题抛出异常。我们可以通过线程池并发执行任务,并确保在发生异常时进行合理处理。

import java.io.File;
import java.util.concurrent.*;public class FileProcessingTask implements Callable<String> {private File file;public FileProcessingTask(File file) {this.file = file;}@Overridepublic String call() throws Exception {if (!file.exists()) {throw new RuntimeException("File not found: " + file.getName());}// 模拟文件处理逻辑return "Processed " + file.getName();}
}public class FileProcessingMain {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(3);Future<String> future = executor.submit(new FileProcessingTask(new File("test.txt")));try {String result = future.get();System.out.println(result);} catch (InterruptedException | ExecutionException e) {System.out.println("Exception occurred: " + e.getCause().getMessage());} finally {executor.shutdown();}}
}

应用场景案例

在金融、物流、电商等系统中,任务通常被分解为多个并发执行的操作。比如,订单系统中的订单处理、支付流程、库存更新等操作通常需要并发处理。在这些场景中,一旦发生异常,必须确保异常得到及时处理和记录,以防止业务流程中断。

优缺点分析

优点:

  • 提高系统健壮性:通过捕获和处理线程中的异常,避免因异常导致整个系统的不稳定性。
  • 提升开发效率:通过良好的异常处理机制,可以更容易调试和定位线程中的问题。

缺点:

  • 增加复杂度:过多的异常处理逻辑可能会导致代码变得冗长,增加维护难度。
  • 隐蔽性问题:在复杂的线程池和并发场景中,如果异常处理不当,可能会掩盖一些严重的问题。

核心类方法介绍

  • Thread.setUncaughtExceptionHandler(UncaughtExceptionHandler handler): 设置线程的异常处理器。
  • Future.get(): 在调用时捕获线程池任务抛出的异常。
  • Callable.call(): 可抛出异常的任务接口,实现任务时可以抛出检查异常。

测试用例

测试代码

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;public class ThreadExceptionTest {@Testpublic void testThreadExceptionHandling() {Thread thread = new Thread(() -> {throw new RuntimeException("Test Exception");});thread.setUncaughtExceptionHandler((t, e) -> {System.out.println("Exception: " + e.getMessage());});thread.start();// 验证线程抛出的异常被处理assertThrows(RuntimeException.class, () -> {thread.join();});}
}

测试代码分析

针对如上示例代码,这里我给大家详细的代码剖析下,以便于帮助大家理解的更为透彻,帮助大家早日掌握。在这个测试用例中,我们演示了如何在Java中处理线程抛出的异常。以下是对代码的详细解析:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;public class ThreadExceptionTest {@Testpublic void testThreadExceptionHandling() {Thread thread = new Thread(() -> {throw new RuntimeException("Test Exception");});thread.setUncaughtExceptionHandler((t, e) -> {System.out.println("Exception: " + e.getMessage());});thread.start();// 验证线程抛出的异常被处理assertThrows(RuntimeException.class, () -> {thread.join();});}
}
1. 创建线程并抛出异常
Thread thread = new Thread(() -> {throw new RuntimeException("Test Exception");
});

我们创建了一个新的线程,并在该线程中直接抛出了一个RuntimeException,其消息为“Test Exception”。这个异常会在线程运行时被抛出。

2. 设置异常处理器
thread.setUncaughtExceptionHandler((t, e) -> {System.out.println("Exception: " + e.getMessage());
});

我们为线程设置了一个UncaughtExceptionHandler,它的作用是捕获线程中未处理的异常。当线程抛出未捕获的异常时,UncaughtExceptionHandler会处理这些异常。在这里,我们只是将异常消息打印到控制台。

3. 启动线程
thread.start();

我们启动了线程,使其开始执行。

4. 验证异常处理
assertThrows(RuntimeException.class, () -> {thread.join();
});

我们使用assertThrows来验证异常是否被正确处理。assertThrows用于检查在执行thread.join()时是否抛出了指定类型的异常。在这个测试中,thread.join()会等待线程结束,虽然join()方法本身不会抛出异常,但我们在这里测试线程是否被正确处理。

说明
  • 异常处理器的作用:通过设置UncaughtExceptionHandler,我们确保了即使线程内部抛出异常,也能有专门的处理机制进行响应。这样可以避免未捕获异常导致的程序崩溃。
  • assertThrows的作用assertThrows用于检查在某个操作过程中是否抛出了预期的异常。在本例中,它用于确保线程异常得到了处理。
小结

这段代码演示了如何在Java中为线程设置异常处理器,确保线程抛出的异常能被捕获并处理。通过这种方式,我们可以在多线程环境中更好地控制异常,从而提高程序的稳定性和健壮性。

总结

在多线程编程中,异常处理是保证线程安全和程序稳定性的关键部分。通过使用UncaughtExceptionHandler,可以有效捕获和处理线程中发生的未捕获异常。结合适当的测试用例,我们可以确保异常处理机制的有效性,进而保障整个系统的健壮性。

小结

Java的多线程异常处理是确保并发程序稳定性的重要工具。通过使用UncaughtExceptionHandler、线程池中的FutureCallable接口等机制,开发者可以有效处理线程中的异常问题,确保多线程任务的安全执行。

总结

通过本文的介绍,我们详细了解了如何在Java的多线程环境下处理异常。合理的异常处理机制不仅能提高程序的稳定性,还能帮助开发者更快地定位问题。在多线程开发中,提前设计并考虑好异常处理逻辑,是保障系统健壮性的重要一步。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

相关文章:

Java线程的异常处理:确保线程安全运行

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云/阿里云/华为云/51CTO&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互…...

nvim 打造成可用的IDE(2)

上一个 文章写的太长了&#xff0c; 后来再写东西 就一卡一卡的&#xff0c;所以新开一个。 主要是关于 bufferline的。 之前我的界面是这样的。 这个图标很不舒服有。 后来发现是在这里进行配置。 我也不知道&#xff0c;这个配置 我是从哪 抄过来的。 测试结果&#xff1…...

如何当前正在运行的 Elasticsearch 集群信息

要查看当前正在运行的 Elasticsearch 集群信息&#xff0c;可以通过以下几种方法&#xff1a; 1. 使用 _cluster/health API _cluster/health API 返回集群的健康状态、节点数量、分片状态等信息。可以用 curl 命令直接访问&#xff1a; curl -X GET "http://localhost…...

PHP Filesystem:深入解析与实战应用

PHP Filesystem:深入解析与实战应用 引言 PHP作为一种流行的服务器端编程语言,提供了强大的文件系统操作功能。本文将深入探讨PHP的Filesystem函数,这些函数允许开发者访问和操作服务器上的文件系统。无论是进行基本的文件操作,还是实现复杂的文件管理系统,PHP的Filesys…...

pdf提取文本,表格以及转图片:spire.pdf

文章目录 &#x1f412;个人主页&#xff1a;信计2102罗铠威&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380; 1. pdfbox1.1导入pdfbox 的maven依赖1.1 提取文本1.2 提取文本表格&#xff08;可自行加入逻辑处理&#xff09;1.3 pdf转换成图片代码&…...

jQuery UI 主题

关于“jQuery UI 主题”&#xff0c;我找到了一些有用的信息。 首先&#xff0c;jQuery UI 主题允许开发人员无缝集成UI小部件到他们网站或应用程序的外观和感观。每个插件通过CSS定义样式&#xff0c;包含两层样式信息&#xff1a;标准的jQuery UI CSS框架样式和具体的插件样…...

C# GDI+的DrawString无法绘制Tab键的现象

【啰嗦2句】 现在用C#的人很少了吧&#xff1f;GDI更少了吧&#xff1f;所以这个问题估计也冷门。没关系&#xff0c;分享给特定需要的人也不错。 【问题现象】 工作中开发了一个报告编辑器&#xff0c;实现图文排版等功能&#xff0c;用着没什么问题&#xff0c;直到有一天…...

C# GID+绘制不透明和半透明的线条

绘制线条时&#xff0c;必须将 Pen 对象传递给 DrawLine 类的 Graphics 方法。 Pen 构造函数的参数之一是 Color 对象。 若要绘制不透明的线条&#xff0c;请将颜色的 alpha 分量设置为 255。 若要绘制半透明的线条&#xff0c;请将 alpha 分量设置为从 1 到 254 的任何值。 在…...

L4-Prompt-Delta

Paper List PromptPapers:https://github.com/thunlp/PromptPapersDeltaPapers: https://github.com/thunlp/DeltaPapers Programming Toolkit OpemPrompt: https://github.com/thunlp/OpenPromptOpenDelta: https://github.com/thunlp/OpenDelta 一、传统微调方法&#xff1…...

Qt 自定义控件(Qt绘图)

一、QPaintEvent绘图事件1、QPaintEvent是Qt框架中一个重要的事件类&#xff0c;专门用于处理绘图事件。 2、当Qt视图组件需要重绘自己的一部分时&#xff0c;就会产生QPaintEvent事件。 3、Qt视图组件重绘自己&#xff0c;通常发生在以下情况: (1)、窗口第一次显示时: 当窗…...

electron 上怎么用node 调用 c++ 提供的方法

背景 在 Electron 上调用 C 代码的场景主要出现在需要执行高性能、低延迟的任务&#xff0c;或者需要与现有的本地 C 库集成时。这些场景往往涉及底层系统交互、性能优化或跨平台兼容性需求。 我们都知道c 的性能和安全性都比JavaScript 要高&#xff0c;但我认为在 Electron …...

Chromium 132 编译指南 Windows 篇 - Git 初始化设置 (四)

1. 引言 在 Chromium 编译指南系列的前几篇文章中&#xff0c;我们已经完成了编译环境的基础设置和关键环境变量的配置。本篇将重点介绍 Git 的安装与初始化配置&#xff0c;这是获取和管理 Chromium 源代码的重要前提。 2. 安装 Git 在 Windows 环境下&#xff0c;Git 并不…...

day03-前端Web-Vue3.0基础

目录 前言1. Vue概述2. 快速入门2.1 需求2.2 步骤2.3 实现 3. Vue指令3.1 介绍3.2 v-for3.2.1 介绍3.2.2 演示3.2.3 v-for的key3.2.4 案例-列表渲染 3.3 v-bind3.3.1 介绍3.3.2 演示3.3.3 案例-图片展示 3.4 v-if & v-show3.4.1 介绍3.4.2 案例-性别职位展示 3.6 v-model3.…...

Windows 下Mamba2 / Vim / Vmamba 环境安装问题记录及解决方法终极版(无需绕过triton)

导航 安装教程导航 Mamba 及 Vim 安装问题参看本人博客&#xff1a;Mamba 环境安装踩坑问题汇总及解决方法&#xff08;初版&#xff09;Linux 下Mamba 及 Vim 安装问题参看本人博客&#xff1a;Mamba 环境安装踩坑问题汇总及解决方法&#xff08;重置版&#xff09;Windows …...

GitLab本地服务器配置ssh和克隆项目

1. 本地安装好git git链接&#xff1a;https://git-scm.com/downloads/win 无脑点击下一步安装即可,打开Git Bash命令终端如下&#xff1a; 2. 配置本地用户名和邮箱 git config --global user.name "你的名字" git config --global user.email "你的邮箱&quo…...

Win10和11 git/Android Studio遇到filename too long问题的解决

1、打开windows长文件、长路径支持&#xff1a; 可以参考这篇文章&#xff1a; 修改注册表方法&#xff1a; 使用Admin登陆machine&#xff0c;在run中输入regedit并回车&#xff1b; 找到路径 ’Computer -> HKEY_LOCAL_MACHINE -> SYSTEM -> CurrentControlSet -&g…...

【JavaWeb学习Day11】

java程序操作数据库&#xff08;JDBC&#xff09; JDBC:&#xff08;Java DataBase Connectivity&#xff09;&#xff0c;就是使用Java语言操作关系型数据库的一套API。 本质&#xff1a; 1.sun公司官方定义的一套操作所有关系型数据库的规范、即接口。 2.各个数据库厂商去…...

rom定制系列------小米max3安卓12 miui14批量线刷 默认开启usb功能选项 插电自启等

小米Max3是小米公司于2018年7月19日发布的机型。此机型后在没有max新型号。采用全金属一体机身设计&#xff0c;配备6.9英寸全面屏.八核处理器骁龙636&#xff0c;后置双摄像头1200万500万像素&#xff0c;前置800万像素.机型代码 &#xff1a;nitrogen.官方最终版为稳定版12.5…...

CES 2025|美格智能高算力AI模组助力“通天晓”人形机器人震撼发布

当地时间1月7日&#xff0c;2025年国际消费电子展&#xff08;CES 2025&#xff09;在美国拉斯维加斯正式开幕。美格智能合作伙伴阿加犀联合高通在展会上面向全球重磅发布人形机器人原型机——通天晓&#xff08;Ultra Magnus&#xff09;。该人形机器人内置美格智能基于高通QC…...

汽车电子相关的协议UDS、DOIP、CAN

UDS协议 UDS&#xff08;Unified Diagnostic Services&#xff0c;统一诊断服务协议&#xff09; 是一种标准化的通信协议&#xff0c;广泛应用于汽车电子系统中&#xff0c;尤其是在车辆诊断和服务过程中。它用于车辆的诊断、维护、控制和测试&#xff0c;支持通过车载诊断接…...

k8s笔记29--使用kyverno提高运维效率

k8s笔记29--使用kyverno提高运维效率 介绍原理安装应用场景自动修正测试环境pod资源强制 Pod 标签限制容器镜像来源禁止特权容器其它潜在场景 注意事项说明 介绍 Kyverno是一个云原生的策略引擎&#xff0c;它最初是为k8s构建的&#xff0c;现在也可以在k8s集群之外用作统一的…...

Life Long Learning(李宏毅)机器学习 2023 Spring HW14 (Boss Baseline)

1. 终身学习简介 神经网络的典型应用场景是,我们有一个固定的数据集,在其上训练并获得模型参数,然后将模型应用于特定任务而无需进一步更改模型参数。 然而,在许多实际工程应用中,常见的情况是系统可以不断地获取新数据,例如 Web 应用程序中的新用户数据或自动驾驶中的…...

libc.so.6不兼容

1、查看电脑所有libc.so.6 daviddavid-Shangqi-X4270:~/MySoft/ubuntusoft$ locate libc.so.6 /home/david/MySoft/ubuntusoft/EXEApp/libc.so.6 /home/david/MySoft/ubuntusoft/EXEApp_TEST/libc.so.6 /home/david/MySoft/ubuntusoft/RTMG_APP/libc.so.6 /home/david/MySoft/…...

树的模拟实现

一.链式前向星 所谓链式前向星&#xff0c;就是用链表的方式实现树。其中的链表是用数组模拟实现的链表。 首先我们需要创建一个足够大的数组h&#xff0c;作为所有结点的哨兵位。创建两个足够大的数组e和ne&#xff0c;一个作为数据域&#xff0c;一个作为指针域。创建一个变…...

AsyncOperation.allowSceneActivation导致异步加载卡死

先看这段代码&#xff0c;有个诡异的问题&#xff0c;不确定是不是bug public class Test : MonoBehaviour {void Start(){StartCoroutine(LoadScene(Ego.LoadingLevel));}IEnumerator LoadScene(string sceneName){LoadingUI.UpdateProgress(0.9f);yield return new WaitForS…...

如何搭建 Vue.js 开源项目的 CI/CD 流水线

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…...

单通道串口服务器(三格电子)

一、产品介绍 1.1 功能简介 SG-TCP232-110 是一款用来进行串口数据和网口数据转换的设备。解决普通 串口设备在 Internet 上的联网问题。 设备的串口部分提供一个 232 接口和一个 485 接口&#xff0c;两个接口内部连接&#xff0c;同 时只能使用一个口工作。 设 备 的网 口…...

【Excel/WPS】根据平均值,生成两列/多列指定范围的随机数/随机凑出两列数据

原理就是通过随机生成函数和平均值函数。 适用场景&#xff1a;在总体打分后&#xff0c;需要在小项中随机生成小分数 第一列&#xff1a;固定的平均值A2第二列&#xff1a; RANDBETWEEN(A2-10,A210)第三列&#xff1a;根据第二列用平均值函数算除 A2*2-B2这是随机值1的公式&am…...

使用网页版Jupyter Notebook和VScode打开.ipynb文件

目录 正文 1、网页版Jupyter Notebook查看 2、VScode查看 因为总是忘记查看文件的网址&#xff0c;收藏了但分类众多每次都找不到……当个记录吧&#xff08;/捂脸哭&#xff09;&#xff01; 正文 此处以gitub中的某个仓库为例&#xff1a; https://github.com/INM-6/mu…...

记录一下vue2项目优化,虚拟列表vue-virtual-scroll-list处理10万条数据

文章目录 封装BrandPickerVirtual.vue组件页面使用组件属性 select下拉接口一次性返回10万条数据&#xff0c;页面卡死&#xff0c;如何优化&#xff1f;&#xff1f;这里使用 分页 虚拟列表&#xff08;vue-virtual-scroll-list&#xff09;&#xff0c;去模拟一个下拉的内容…...

北京最新疫情情况/seo赚钱方法大揭秘

在我们实际使用 Elasticsearch 时&#xff0c;随着时间的推移&#xff0c;我们会发现有扩容的必要。这个可能由于我们在刚开始创建项目认识不足。我们需要更多的 primary shards&#xff0c;这样可以提高 ingest 的速度。那么我们有什么办法来把之前的一个大的索引变成更多的小…...

企业网站做电脑营销/文章推广平台

问题 当物体正常展示后&#xff0c;设置为实体展示&#xff0c;却无法显示出立体的效果来&#xff0c;按照给出的MeshLambertMaterial材料设置的例子反复尝试都不成功 实例 var cubeGeometry new THREE.BoxGeometry(15, 15, 15); var meshMaterial new THREE.MeshLamebertM…...

网站建设背景图/湖南企业seo优化

1.listbox控件如何多选取值 将listbox控件中的selectionmode属性值设置为multiple,listbox控件可以支持多选 取值问题 假设控件为listbox1 Dim i As Integer Dim str As String For i 0 To ListBox1.Items.Count - 1 If ListBox1.Items(i).Selected …...

网站的网站建设公司/石家庄seo推广优化

Windows2008已经在物理机上装过了&#xff0c;现在的愿望就是想装在自己的本本上。但无法确定它是否会能够完整的支持我小黑所有的驱动&#xff0c;于是我把目光锁定在了同事的那台T41&#xff0c;结果是他的T41很无辜的伦为我的小白鼠。由于光驱烂到不读DVD了&#xff0c;所以…...

网站建设公司十大/小红书关键词搜索量查询

一、首次适应算法&#xff08;First Fit——FF&#xff09; 算法思想&#xff1a; 每次都从低地址查找&#xff0c;找到第一个能满足大小的空闲分区。 如何实现&#xff1a; 空闲分区以地址递增的顺序排列每次分配内存时从低地址顺序查找空闲分区链&#xff08;空闲分区表&…...

用iis浏览网站/bt蚂蚁

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/xmt1139057136/article/details/77983392 甲骨文宣布&#xff0c;Oracle 已选择 Eclipse 基金会作为 Java EE 的新东家。甲骨文与该平台的另外两大贡献者 —— IBM 和 Red Ha…...