作者个人研发在高并发场景下提供了一个简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。开源半年多以来,已成功为十几家中小企业提供精准定时调度解决方案,经受住了生产环境的考验。为了造福更多的童鞋,这里给出开源框架的地址:https://github.com/sunshinelyz/mykit-delay我写了一段时间【高并发专题】,有读者留言说并发编程非常快。难,学到了很多知识,但是在实际工作中却没有办法去做。一个线上的并发问题,不知道这个问题的原因是什么。对于并发编程,看似掌握了,实际使用起来却不是这样!其实造成这种现象的本质原因是没有深入理解并发编程的本质,而学习并发编程的关键是理解三个核心问题:分工、同步、互斥比较官方的解释分工的方式是:分工就是把一个比较大的任务拆分成多个大小合适的任务交给合适的线程去完成,强调性能。如果你还不能理解什么是分工,这里,我们可以做一个假设。假设你是一家XXX上市公司的CEO,你的工作就是如何把公司经营好。然而,如何把公司经营好,涉及的工作很多。我们可以将其视为一项重大任务。如果细看,这个大任务可以包括:人员招聘与管理、产品设计与开发、运营与推广、企业税务等等。如此多的任务,炼化后交给你一个人,你一定要崩溃了。就算能坚持住,估计一个人完成这些任务,黄花菜也要凉了!那个时候,你大概会偷偷躲在角落里唱“爽”。..所以,如果你真的想管理好你的公司,你需要把这些工作分解,分工细化,把人员招聘和管理的任务交给人力资源部,把产品设计交给设计部.,将产品开发交给开发部,将运营推广交给运营市场部,将企业税务交给财务部。这时候,你的任务就是及时了解各部门的工作情况,统筹协调各部门的工作,思考如何规划公司的未来。其实,你在这里把管理公司的任务拆解划分后,你会发现各个部门之间的工作其实是并行执行的。例如:人力资源部门在管理员工绩效考核时,产品设计开发部门同时在设计开发公司的产品。同时,公司运营也在与设计开发沟通如何更好的改进公司的产品。推广部正在加紧宣传推广公司产品。财务部门正在统计和计算公司的各种财务报表。一切都是那么的有条不紊!因此,在实际工作中安排合适的人做合适的事是非常重要的。映射到并发编程领域时也是如此。如果你把所有的任务都交给一个线程去执行,就等于把公司的所有事情都交给了你一个人。干完活,黄花菜也凉了。因此,在并发编程中,我们也需要将任务拆解,分工到合适的线程去完成。在并发编程领域,还有一个问题需要注意:分工到合适的线程。也就是说,本该由主线程完成的任务不应该交给子线程处理,否则无法解决问题。这就像一家公司的CEO委托产品开发人员如何规划公司的未来。这不仅没有规划公司的未来,甚至与公司的价值观背道而驰。JavaSDK中:Executor、Fork/Join、Future都是实现分工的方式。同步并发编程中的同步主要是指一个线程执行完任务后如何通知其他线程继续执行,强调性能。任务拆分好,给大家合理分工之后,接下来就是如何同步大家的任务了。假设小明是前端开发人员,需要等待小刚的界面完成渲染页面数据,而小刚在写界面的时候需要等待小李的服务开发完成。也就是说,任务之间存在依赖关系,只有在前面的任务完成后才能执行后面的任务。在实际工作中,此类任务的同步大部分依赖于人与人之间的交流。小李的服务写好后,告诉小刚,小刚会马上进行界面开发,等待小刚的界面开发完成。之后告诉小明,小明马上调用接口将返回的数据渲染到页面上。这种同步机制映射到并发编程领域,即一个线程的任务执行完毕后,通知其他后续线程执行该任务。对于线程间的这种同步,我们可以用下面的if伪代码来表达。if(上一个任务完成){执行当前任务}else{继续等待上一个任务的执行}为了更及时的判断上一个任务是否已经完成,我们还可以使用while伪代码来表达。while(上一个任务没有完成){continuetowaitfortheexecutionoftheprevioustask}执行当前任务上面伪代码的意思是一样的:当线程执行条件不满足时,线程需要继续执行等待,一旦满足条件,就需要唤醒等待线程继续执行。在并发编程领域,一个典型的场景就是生产者-消费者模型。当队列满时,生产者线程需要等待,当队列未满时,生产者线程需要被唤醒;当队列为空时,消费者线程需要等待,当队列不为空时,消费者需要被唤醒。我们可以使用以下伪代码表示生产者-消费者模型。Producerwhile(queueisfull){producerthreadwaits}唤醒producerconsumerwhile(queueisempty){consumerwaits}唤醒consumerJavaSDK提供了一些线程间同步的工具类,例如:CountDownLatch、CyclicBarrier等。相互exclusion只允许一个线程同时访问共享变量,强调线程执行任务的正确性。在并发编程领域,分工和同步强调任务执行的性能,而线程间的互斥则强调线程执行任务的正确性,即线程安全问题。如果多个线程同时访问同一个共享变量,可能会出现意想不到的后果,而这种意想不到的后果主要是由线程的可见性、原子性和顺序问题产生的。解决可见性、原子性和有序性问题的核心是互斥。关于互斥,我们可以用现实中的一个场景来描述:多个岔路口的车辆需要并入一条道路,而这条道路一次只能允许一辆车通过。此时,车辆需要排队进入路口。Java中提供的synchronized、Lock、ThreadLocal、final关键字都可以解决互斥问题。例如,我们以synchronized为例来说明如何实现线程间的互斥,伪代码如下。//修改方法publicsynchronizedvoidxxx(){}//修改代码块publicvoidxxx(){synchronized(obj){}}//修改代码块publicvoidxxx(){synchronized(XXX.class){}}//修改静态方法publicsynchronizedstaticvoidxxx(){}总结并发编程旨在最大限度地利用计算机资源并提高程序执行的性能。这就需要线程之间的分工和同步来实现。在保证性能的同时,还要保证线程安全。这是另一个需要保证线程之间的互斥。并发编程的难题往往是由可见性、原子性和顺序性的问题引起的。所以,我们在学习并发编程的时候,首先要了解线程之间的分工、同步和互斥。本文转载自微信公众号“冰河科技”,可通过以下二维码关注。转载本文请联系冰川科技公众号。
