大概每个人都知道并发编程是一项非常重要的技术,无论访谈或工作频率如何。
当然,如果它是个人小工具,那绝对不是特别关注这一点。
一致的编程多线程编程。
但是多线程必须比单个线程更有效吗?
不一定,这取决于特定的业务环境。多个线程将继续抓住资源,因此有时多线程是相对耗时的。
1.您是否想知道计时任务?课程真的可以执行常规任务吗?
答案是肯定的。有些源代码,它们的底层还使用线程类。
使用类可以执行最简单的计时任务,该方法中有一个死周期(当然还有其他方法)可以执行我们自己的任务。需要特别注意的一种事情是需要捕获。否则,如果发生异常,它将直接退出周期,而下次将无法执行。
但是,此方法的定时任务只能定期执行,并且不能在特定时间点支持时间执行。
特别提醒建议将线程定义,并且可以通过方法设置设置该线程,以使其在后台静静地执行。
使用方案:例如,在项目中,有必要每5分钟进行一次,或每10分钟读取一次模板文件,以及一些简单的周期性任务场景。
使用定时任务的优势和缺点:
2.有时,监视器,我们需要编写一个监视器来监视某些数据中的更改。
例如:当我们使用它时,我们需要更改听力的更改,并且我们可以及时将数据库中的数据同步到另一个业务数据库。
如果您直接编写监视器以收听数据,那么它太无聊了。我们想实现这样的函数:配置中心中有一个开关,是否打开了侦听器,以及是否打开使用单线读异步执行的使用。
主要代码如下:
在该线程中执行异步执行方法的特定任务的方法中打开线程。然后,您可以通过调用停止方法来停止线程。
其中,由关键字控制的运行变量可以用作开关,可以控制线程中的状态。
接下来,有一个更关键的点:如何通过配置中心配置控制此开关?
以配置为例,在修改配置中心背景中的配置后,我们将自动获取最新的配置核心代码:如下:
通过注释,您可以监视配置参数中的更改。
如果配置了开关,则调用类的开始方法打开数据同步函数。如果配置了开关,则调用类的方法将自动停止数据同步函数。
3.在一些高串联方案中收集日志,我们需要收集一些用户的日志(例如:日志登录日志),并将其写入数据库以促进分析。
但是,因为在项目中,没有消息中间件,例如:
如果日志直接写入数据库,则可能会影响接口性能。
因此,每个人自然都会想到异步治疗。
意识到这一需求的最简单方法是打开线程并将数据异步地与数据库编写。
这可以做到。
但是,如果用户在操作中登录,则比异步写入数据库的时间要少得多。结果,生产日志的速度比消费者日志的速度快得多,最终的性能瓶颈在消费方面。
实际上,有更多优雅的方法来处理它。尽管没有消息的中间信息,但它借用了它的思想。
此记录登录日志的功能分为:日志生产侧,日志存储侧和日志消耗侧。
首先定义阻塞队列。
然后定义日志生产者。
接下来,定义了日志的消费者。
当然,此示例在单个线程中使用单个线程登录日志。为了提高性能,它还可以使用线程池来处理业务逻辑(例如:写入数据库)。
4. Excel Imports我们通常可能会从运营同学那里收到Excel数据导入需求,例如:将大型类中的所有子类导入或引入许多新的供应商数据等等。
我们以供应商数据的进口为例。它涉及漫长的业务流程的业务流程,例如:
ETC。
如果在程序中,分析并读取所有数据。要使用单线线程处理业务逻辑,则可能需要很长时间。
为了提高数据导入的效率,有必要使用多线程处理。
当然,有很多方法可以在中国实现多线程。实现以下谈话的最简单方法:。
伪代码如下:
这是一个并行执行流,默认情况下实现,可以提高多线程任务的速度。
处理过程将分为划分,其核心想法是:。每个小任务可以单独执行,最终将总结所使用的任务的执行结果。
简短介绍的原理,下面是图片:
当然,除了Excel导入外,还有类似的阅读文本文件,也可以以类似的方法处理。
温暖的提醒,如果一次进口的数据有很多数据,则使用多线程处理可能会飙升系统的使用率,并且需要特别注意。
5.在查询接口中很多次,我们需要在特定查询接口中调用其他服务的接口。结合数据后,返回在一起。
例如,有这样的业务场景:
用户信息查询接口需要返回:用户名,性别,级别,头像,点,增长价值和其他信息。
用户名,性别,等级和头像在用户服务中。积分在整体服务中,增长价值在增长价值服务中。为了总结这些数据以均匀返回,需要提供另一种外部接口服务。
因此,用户信息查询接口需要调用用户查询接口,点查询接口和增长值查询接口,然后汇总数据以均匀返回。
呼叫过程如下图所示:
致电总时间以调用远程接口530ms = 200ms + 150ms + 180ms
显然,这种串行调用远程接口性能非常糟糕。调用远程接口消耗的总时间是所有远程接口时间的总和。
那么如何优化远程接口的性能?
由于多个远程接口非常差,为什么不更改为平行呢?
如下所示:
调用远程接口的总耗时(即最长的远程接口调用)
在Java8之前,您可以通过实现接口获得线程结果。
此功能将在稍后通过课程实施。我们在这里考虑:
提醒一个温暖的提醒,别忘了使用这两种方法。在示例中,我用它来指示自定义线程池。为了防止高汇编场景,线程太多。
6.获取用户的上下文,不知道您在项目开发中是否遇到了如此需要:在用户登录后,在所有请求接口中,您可以通过公共方法?
获得的用户的上下文考虑了它。
它包含一个内部的对象,该对象负责保留当前线程用户的上下文。当然,为了确保在线程池中,还可以从用户的上下文中获得正确的用户信息,并且在此处使用ALI。伪代码如下:
为什么使用ali,而不是普通?在线程池中,线程反复重复使用,从而从普通人那里获得了正确的用户信息。父线程中的参数不能传递给子线程,此问题是解决方案很好。
然后,在项目中定义了全局拦截器,用户辩称中间。伪代码如下:
当用户请求我们的接口时,将首先触发拦截器。如果您可以获取,则意味着用户已登录,并且用户信息设置为类。
接下来,在服务的较低级别,即业务层的方法,您可以通过该方法轻松获取所需的用户上下文信息。
该用户系统的想法非常好,但是在深入使用后,发现了一个小情节:
引用了服务和消费者服务,并且该层中的两个服务都可以直接调用。
我们都知道用户需要在服务中登录,并且消费者服务无需登录。
如果中间的一种方法是用于开发,则用户的上下文在方法的深处使用。但是,后来,一个新的英俊的家伙也称为消费者中的方法。没有注意到这个小型器官,他将被招募,并且存在一个找不到用户背景的问题。
因此,我当时的第一个想法是:该代码不兼容,因为这些问题偶尔会发生。
解决此问题实际上非常简单。首先判断您是否可以从中获取用户信息。如果没有,您可以获取配置系统用户信息。伪代码如下:
如果仅在一个或两个地方添加,则可以使用简单且无障碍的代码。
此外,众所周知,过去,它是处理时间的工具,它是非线程的。换句话说,使用此方法来分析安全性日期。
为了避免线程安全的出现,我们可以定义对象。但是,如果您必须将其定义为静态变量,则可以使用保存日期并解决线程安全问题。
8.当我看到一些同事在传递参数之前编写代码时,一个非常有趣的用法,即使用传输参数。
什么是MDC?
这是包装下的课程。它的全名是,我们可以认为它是安全存储诊断日志的容器。
底层用于保存数据。
例如,现在有一个方案:当我们使用远程接口时,有时我们会在中间传递信息:查询日志以串联连接完整的请求链接以快速找到问题很方便。
这种业务方案可以通过接口实现。具体做法如下:
第一步是定义截距所有接口请求,该请求设置为中间:
第二步是实现接口,获取当前请求,然后将其设置为中间:
第三步是定义配置类,以及上面定义的类:
其中实际上是使用工具存储和获取
当然,在此示例中没有特定的方法来修改演示类别的方法。在执行接口方法之前,我们可以生成类的添加方法,然后可以将类的添加方法添加到中间。
使用参数(例如保存)的根本原因是,当用户向应用程序服务器请求时,将从线程池分配线程以处理请求。
在请求的整个过程中,保存到线程的参数也是独有的,因此不会存在线程安全问题。
9.高并发性的模拟有时书面界面,在低并发场景中,没有问题。
但是,如果出现高的并发呼叫,可能会有一些意外的问题。
为了防止类似的事情发生,通常有必要在启动项目之前进行界面。
当然,有更多成熟的压力测试工具,例如:
如果您认为下载压力测试工具更麻烦,则还可以编写一个简单的仿真和并发操作工具,例如:::
10.在高分子的情况下,可以说MQ消息信息的问题如下,并且实际上无法从根本上解决它。在表面上,它已经解决了,但是我做了N't知道何时会出来,例如这次:
一个下午,产品开始说:几家商人抱怨了,他们说菜肴被推迟了,并检查了原因。
这个问题有点奇怪。
你为什么这么说?
首先,这次有点奇怪。您通常有问题吗?不是在中午还是晚上全部?为什么这个问题在下午出现?
根据我过去积累的经验,我直接阅读的数据确实具有上述消息的积压,但是这次,每个消息的积压都超过100,000,没有消费,这是数百个积压过去的新闻数量更多。这个新闻的积压非常不寻常。
我迅速检查了服务监视,以查看消费者是否被挂断电话,但幸运的是,我没有挂起它。检查服务日志是否不异常。这次,我有些困惑。我问我是否急着问订单小组是否在下午发生?他们说下午有促销活动,并为某些商人提供了一批订单信息。
目前,我突然像一个梦一样醒来,这是他们批次发送消息的消息引起的一个问题。为什么我们不通知我们?这太坑了。
尽管问题的原因是,我该如何处理我面前的积压新闻?
目前,如果没有直接调整该数字,则将历史新闻存储在固定分区中,只有新的新闻才能到达新分区。我们需要处理的是现有分区。
不可能直接添加服务节点,因为允许同一组的多个组被消费,但是同一组中的多重消费者不允许一个分区消费,这可能会导致资源浪费。
看来它仅被使用。
为了紧急解决问题,我更改为处理中的消息,并配置了核心线程和最大线程数。
粗糙用法如下:
果然,调整后的积压量确实很快减少。大约半小时后,对积压的信息进行了非常顺利的处理。
但是目前,有一个更严重的问题:我收到了一封报告电子邮件,两个订单系统的节点均已下降。
11.多线程中的统计数量,有时需要统计数量。例如,当引入多线程的供应商数据数量时,供应商数量的成功介绍的数量为。
如果目前使用计数++的数量,则最终结果可能不准确。由于计数++不是原子操作,如果多个线程同时执行操作,则可能发生统计数字。
为了解决这个问题,需要使用的袋子下的班级,例如:
底层清楚地使用了+。
简单地说,这是一个。
相反,这意味着。
它的实现逻辑是将内存位置与其进行比较。如果相等,则更换内存位置的值。如果不相等,请不要进行任何操作。
12.延迟的定时任务通常需要延迟数据的处理。例如,如果在用户下订单后30分钟内未完成付款,则系统会自动取消订单。
它可以在这里实施。
这是由版本引入的定时任务,该任务位于并发软件包下。
SendiuledExeCutorService基于多线程。设计的最初意图是解决单线执行的问题。多个任务将相互影响。
它主要包含4种方法:
实施此计时任务的特定代码如下:
调用类实现周期任务的方法,每1秒执行一次,然后对每个延迟执行1秒钟。
此计时任务是阿里巴巴开发人员规格中使用的解决方案。这是多线程执行周期任务的好选择。
使用类用于延迟的时序任务的优势和缺点:
当然,您还可以使用分布式的定时任务,例如:或类。
实际上,在实际工作中,我使用的是多线场景远远超过12种类型。在这里,我只是吸引砖块,并介绍一些我认为的常见业务场景。
文章来自:su san Say技术
原始:https://juejin.cn/post/7101568480960315400