哈喽,大家好,我是了不起。
最近把旧电脑搞成了NAS,就像折腾着搞一下内网穿透。看了好几个教程,发现都不是最新版本,根本无法使用。本次给大家分享猴子都能做到的内网穿透步骤。
Java 's Blog
哈喽,大家好,我是了不起。
爬虫,也被称为网络爬虫或网络蜘蛛,是一种自动化的网络机器人,其主要功能是按照一定的规则,自动浏览互联网并从网页中提取信息。
作为一个开发人员,相信大家都尝试过写一些爬虫,合理的利用一些爬虫工具,对于我们一些还是挺有帮助的。
比如自动化测试,使用爬虫技术对网站进行自动化测试,检查链接是否有效,确保网站内容的正确显示。
今天就给大家介绍一款开源的爬虫工具,不用写代码即可完成爬虫。
在数字化高速发展的今天,确保在线服务的可靠性和可用性变得比以往任何时候都重要。这就需要一款强大的监控工具,以确保你的服务器、网站和API始终在线。
在众多监控工具中,Uptime Kuma作为一款开源、现代化的服务监控解决方案,正逐渐成为众多开发者和系统管理员的心头好。
本文将为您详细介绍Uptime Kuma的作用、特性以及如何轻松安装并使用它来守护您的在线业务。
Uptime Kuma是一个开源监控工具,它允许你监控你的服务,并确保你是第一个知道它们何时下线的人。与传统的SaaS监控服务(如UptimeRobot)不同,Uptime Kuma提供了一个可完全控制和定制的环境。
它有以下主要特点:
Uptime Kuma提供了多种安装选项,以适应不同的用户需求。可以通过Docker容器快速安装,也可以从源代码构建。这里基本演示Docker的安装方法:
首先确保服务器已经安装了Docker: 如果你还没有Docker,首先需要安装它。根据你的操作系统,你可以从Docker官网下载合适的安装包。
1 |
|
1 |
|
上面的命令会创建一个新的Uptime Kuma容器,名为uptime-kuma
,并且将容器的3001端口映射到主机的3001端口。
http://localhost:
,你将看到Uptime Kuma的登录页面,按照初次启动向导完成安装过程。1 |
|
编写docker-compose.yaml
文件,用docker compose up -d
启动即可。
初始化和配置和上述一致。
进一步的配置和定制教程可以在Uptime Kuma的GitHub文档中找到,包括如何添加监控项、配置通知方式等。
Uptime Kuma是一个功能强大且易于使用的监控工具,它是为希望完全控制监控过程的团队和个人设计的。
它的自托管特性意味着没有外部依赖,你数据的隐私性和安全性得到了保证。
除此之外,它开源且完全免费,适合希望有成本效益解决方案的企业和开发者。如果你正在寻找一个灵活而且强大的监控工具,Uptime Kuma无疑是一个值得考虑的选择。
Java 8 引入了强大的 Stream API,为处理集合数据提供了简洁、高效的解决方案。
其中,parallel()
方法为流处理引入了并行化能力,允许开发者充分利用多核处理器的优势,大幅提升大规模数据集的处理效率。
本篇文章将带你开启并行流处理之旅,认识 Java 8 Stream API 中的 parallel()
。
parallel()
是 Java 8 Stream API 中的一个方法,用于将一个顺序流转换为并行流。并行流是一种可以同时在多个线程上执行操作的流,它将流的元素分割成多个子集,每个子集在不同的线程上独立处理,最后将结果合并。使用 parallel()
方法可以轻松开启并行流处理模式,无需显式管理线程和同步。
1 |
|
在这个示例中,parallel()
方法将顺序流转换为并行流,后续的 filter()
、map()
和 forEach()
操作将在多个线程上并行执行,从而加速数据处理。
并行流处理背后的核心机制主要包括以下几个方面:
并行流根据数据集的大小、处理器核心数等因素动态调整并行度和任务划分策略。对于小规模数据集或不适合并行化的操作,Java 8 会自动退化为顺序流处理,避免不必要的线程开销。
总之,parallel()
方法通过将原始列表拆分成多个子任务,并在独立线程上并行执行流操作链的各个阶段,最后合并处理结果,实现了对列表数据的高效并行处理。
具体的拆分策略和并行执行细节由 JVM 自动管理,开发者无需关心底层实现,只需关注流式编程的高层抽象。
适合parallel()
并行流的应用场景有:
filter()
、map()
、flatMap()
、sorted()
等。场景:在一个数据分析项目中,需要对一个包含百万条记录的数据集进行复杂过滤和计算。使用并行流可以显著加快处理速度,充分利用多核处理器资源。 示例
1 |
|
场景: 假设有一个电商系统需要批量更新大量商品的价格,每个商品的更新过程涉及网络请求到不同服务获取最新价格信息,然后保存到数据库。
示例:
1 |
|
在这个示例中:
parallel()
流操作,使得后续的 map()
操作能并行执行。CompletableFuture
,通过 supplyAsync()
异步调用 PriceService
获取最新价格。thenAcceptAsync()
异步操作。在获取到最新价格之后更新数据库。CompletableFuture.allOf()
等待所有数据库更新操作完成。Java 8 Stream API 中的 parallel()
方法为处理集合数据提供了便捷的并行化途径。
在复杂的异步处理场景中,可以结合 CompletableFuture
与并行流,进一步提升程序的并发性和响应能力。
通过合理使用并行流,开发者可以显著提升大规模数据集处理的性能,充分发挥现代多核处理器的潜力。
然而,使用并行流时也应注意避免数据依赖、状态共享等问题,适时进行性能评估与调整。
哈喽,大家好,MySQL作为广泛使用的开源关系型数据库管理系统,应该没有Java开发没使用过吧。
关于MySQL,我们大部分时间都在聊,如何提高查询效率,今天我们来聊聊如何提高MySQL的插入效率。
一般情况下,数据库是运行在专门的服务器上,提高插入效率最明显的当然是提高服务器配置啦。 比如,使用高性能的CPU和SSD磁盘,使用分布式系统架构,将写入压力分散到多个节点。 这个方式的成本也是最高的,老板们当然不会使用这种方式了。
我们还可以从其他方面入手:
MyISAM
存储引擎,因为其简单的表锁机制和无事务开销而在插入速度上表现更优。考虑到实际的应用场景,我们最可能操作的就是使用第3种实现方式,通过批量插入的方式来提高效率。
常用的批量插入的方式有2种:
insert into xxx (...) values (...),(...),(...)
接下来我们来测试一下这几个方法。
测试的SQL
1 |
|
一、使用 batchXml
1 |
|
二、使用mybatis-flex提供的saveBatch
1 |
|
三、手动控制事务的提交,saveBatchSession
1 |
|
启动代码
1 |
|
使用了3种方式进行测试
未开启批处理,batchXml
未开启批处理,mybatis-flex提供的saveBatch
未开启批处理,saveBatchSession
从这里的结果可以看出,使用 batchXml
的效率是最高的,远远超越其他方式。
但是仔细一想,这些数据应该很不正常,插入1000条数据,竟然需要4秒左右,和单条插入1000次的时间几乎没有区别。
经过一番查询资料,并检查配置,发现果然另有玄机,连接数据库的时候没有开启批处理
开启方式:在spring的配置文件中,连接数据源时,url需要增加 allowPublicKeyRetrieval=true
然后重新测试一遍。
开启批处理,saveBatchXml
开启批处理,mybatis-flex提供的saveBatch
开启批处理,saveBatchSession
这次的结果就比较正常了,可以看出来:
saveBatchSession
最快mybatis-flex提供的saveBatch
因为有些额外的操作,多消耗了10ms左右的时间saveBatchXml
相较于另外两种方式,慢了30ms~40ms。接下来,把每批次的处理数据由1000次增加到10000次,再次进行测试。
开启批处理,saveBatchXml,10000条一批次
开启批处理,saveBatchSession,10000条一批次
开启批处理,mybatis-flex提供的saveBatch,10000条一批次
由此结果可以看出来:
saveBatchSession
和mybatis-flex提供的saveBatch
耗时基本一致saveBatchXml
就明显的慢一些,按照效率差算,差了将近50%的效率
\(\text { 效率差 }=\frac{\text { 较长时间 }- \text { 较短时间 }}{\text { 较短时间 }}=\frac{1200 \mathrm{~ms}-800 \mathrm{~ms}}{800 \mathrm{~ms}}\)综上,提高MySQL插入效率主要可通过调整数据库配置、选择适合的存储引擎以及运用批量插入策略等方式实现。 在实际应用中,尤其是在使用ORM框架进行数据操作时,应合理选择并充分利用批量插入功能,以最大程度提升插入效率。
allowPublicKeyRetrieval=true
saveBatch
即可。在现代软件开发中,异步编程已成为提升系统性能、响应能力和可扩展性的关键手段。Java 8 引入了 CompletableFuture
类,为 Java 平台带来了强大的异步编程能力。
本篇文章将带你认识这个异步编程神器:CompletableFuture
。
CompletableFuture
是 Java 8 引入的 java.util.concurrent
包下的一个类,它代表一个异步计算的结果,可以是已完成、正在进行或尚未开始。
CompletableFuture
提供了一种灵活、类型安全的方式来表达异步操作的生命周期,包括创建、组合、处理结果以及处理异常。其设计灵感来源于函数式编程中的 Promises/Futures 模式,旨在简化异步编程模型,提高代码的可读性和可维护性。
completedFuture(T value)
completedFuture(T value)
是一个静态工厂方法,用于创建一个已经处于完成状态且包含给定结果值的 CompletableFuture
。这适用于预先计算好的结果或常量值,使得其他组件可以以异步形式消费。
supplyAsync(Supplier<U> supplier, Executor executor)
supplyAsync()
方法接受一个 Supplier
函数和一个可选的 Executor
,异步执行 supplier.get()
,并将结果封装到一个新的 CompletableFuture
中。计算在 Executor
管理的线程中进行,不阻塞当前线程。
runAsync(Runnable runnable, Executor executor)
类似于 supplyAsync()
,runAsync()
接受一个 Runnable
任务和一个 Executor
,异步执行任务。由于 Runnable
没有返回值,runAsync()
返回的 CompletableFuture
完成时没有结果。
thenApply(Function<? super T,? extends U> fn)
在当前 CompletableFuture
完成后,应用给定的 Function
处理结果,并返回一个新的 CompletableFuture
,其结果为 Function
应用后的值。
thenAccept(Consumer<? super T> action)
当当前 CompletableFuture
完成后,执行给定的 Consumer
消费结果。由于 Consumer
没有返回值,返回的 CompletableFuture
完成时没有结果。
thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
当当前 CompletableFuture
与另一个 CompletionStage
(如另一个 CompletableFuture
)都完成时,应用给定的 BiFunction
合并两个结果,并返回一个新的 CompletableFuture
。
exceptionally(Function<Throwable,? extends T> fn)
当当前 CompletableFuture
因异常而未能正常完成时,应用给定的 Function
处理异常,并返回一个新的 CompletableFuture
,其结果为 Function
应用后的值。
handle(BiFunction<? super T, Throwable, ? extends U> fn)
无论当前 CompletableFuture
正常完成还是因异常未能完成,都会应用给定的 BiFunction
处理结果或异常,并返回一个新的 CompletableFuture
。
allOf(CompletableFuture<?>... cfs)
创建一个新的 CompletableFuture
,当所有给定的 CompletableFuture
都完成(不论成功与否)时,新 CompletableFuture
完成。
anyOf(CompletableFuture<?>... cfs)
创建一个新的 CompletableFuture
,当任意一个给定的 CompletableFuture
完成时,新 CompletableFuture
完成。
CompletableFuture
的使用场景很广泛,例如
这里以第一个场景举例:
场景:在一个订单处理系统中,需要查询订单的详细信息、关联的商品信息以及用户的个人信息。为减少查询延迟,可以使用 CompletableFuture
对每个查询进行异步执行,并在所有查询完成后合并结果。
示例:
如果我们不使用Java8提供的这个CompletableFuture
来实现
1 |
|
使用CompletableFuture
实现
1 |
|
在这个示例中:
CompletableFuture
之后,代码量减少了,整洁度和可读性也得到提高。fetchOrderDetails
方法接受一个订单 ID,使用 CompletableFuture.supplyAsync()
异步查询订单、商品和用户信息。CompletableFuture.allOf()
监控所有查询的完成状态。thenApplyAsync()
合并结果,创建一个包含完整订单详情的 OrderDetails
对象。CompletableFuture
作为 Java 8 引入的重要异步编程工具,极大地提升了 Java 平台在应对高并发、高性能场景的能力。
结合 Java 8 的并行流(Stream.parallel()
)与 CompletableFuture
,可以轻松实现数据集的并行处理和结果聚合。
下次给大家聊聊Stream.parallel()
。
哈喽,大家好,我是了不起。
当你遇到PPT的时候,你的内心是什么样子的。
如果需要你写PPT了,那么有几个时间点,你要进行述职汇报,大概率是升职了。或者作为程序员,你的代码之路逐渐走向尾声,以后更多的是需要进行汇报工作,此时你需要领导他人,然后再也没有时间写代码了。关于PPT,每一个程序员都应该重视,毕竟这是你保留饭碗的一项硬技能!