java多个线程完成顺序_进击谷歌:多线程下程序顺序怎么稳定不乱?

8201c831b0f4e5b4c0b4a1e252eaa5fd.png

题目

比如我们有三个方法,类似以下代码

3aa2cfe4719f06c2537d360b0c7ad488.png

分别初始化三个线程去执行这三个方法,每个线程执行的方法可以任意指定,但是方法的执行顺序必须是:Methond1=》Methond2=》Methond3

示例:

6da2e841ec739d52a45979e73cad817b.png

e904f4e2a0988d8d8bc1efca40d4cfdc.png

题解分析

这道题本质上考的是多线程环境资源竞争的问题,在多线程环境下要想以固定某个顺序执行方法,必须要有一个类似屏障的东西来阻止不该执行的线程,或者换句话说必须要有一个机制来顺序化多个线程。这也是我们平时多线程开发环境中必须要面对的问题,现代服务器的cpu都是多核心,我们平时用得最多的java,c#等高级语言是能够利用服务器多核心这个优势的,这里是一个进程内,多线程就可以利用多核心。当然也有一些别的技术,比如Nodejs,虽然执行是单线程的,但是可以利用多进程来提高多物理cpu的利用率。

说的有点远了,接下来还是看这道题,这道题目考验的是多线程下资源的竞争问题和线程间的通信问题,说得直白一点就是:Methond1未执行之前,任何方法都不能执行(这里是指方法内的代码),Methond1执行完之后,会通知执行Methond2的线程,Methond2开始执行,Methond2执行完毕会通知执行Methond3的线程,以此类推。所以这道题的关键在于阻塞某个线程执行和通知某个线程执行。

在很多语言中都提供了lock的机制,或者信号量的机制。这些都是可以实现线程间通信的的解决方案,当然最简单暴力的方式还是通过共享变量的方式来实现通知,虽然有很多缺陷,但是在很多情况下确实是最简单快捷的方案。下边就以c#语言为例:

f6e47267a23a296f1f0091ebe3ea7feb.png

测试执行:

91fbc62e28095c73f0425c902e10a11a.png

不要太纠结以上的代码,以上只是作为抛砖引玉的作用,就算是有执行错误,思路我觉得还是没有问题的,当然确实有很多要优化的地方,比如等待执行的线程一直在耗费cpu资源的情况,可以替换为自旋锁或者混合锁,有兴趣的同学可以进行优化一番。

另辟蹊径

但是,作为语法很优秀的c#怎么能就此止步呢?c#本身提供了Task的机制,可以把它看作是类似golang的协程(虽然不是很像)。基于task的机制我们很容易就完成,task的 ContinueWith机制就是为此而生的,它可以很方便的把多个并行的task串行化,有兴趣的同学可以试一下,但是我要说的并非ContinueWith。既然要执行的顺序化,如果我把执行的代码放在有顺序的容器中,然后按照顺序去执行,岂不快哉?不多废话:

bf3882f79876988623a63401bbc9b7a1.png

测试:

3fcae6a89e75a1340f28f6dca1538acf.png

是不是很爽,毫不犹豫地说c#是一门很优秀的语言,在并发方面做得很优秀。以上Task的代码并非是最优代码,比如 可以用Await来代替 wait(),这样的话在真实环境中可以释放当前线程来提高吞吐量,记住:await方式提高的吞吐量,并非缩短了单次请求的执行时间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值