一段伪代码引发的多线程的思考

xiaoxiao2021-02-28  41

多线程使我们的程序的执行效率得到了很大的提高,但稍有不慎,它也给我们程序带来致命一击,下面就通过一段伪代码来解析平时容易犯错误的一个问题,代码如下: /** * 执行一个task,停止正在播放的任务,然后重新开始播放 */ public void exeTask(){ MsgSendUtil.sendData("stop"); (1) MsgSendUtil.sendData("play"); (2) } /** * 通过线程池发送数据 */ public void sendData(final String data){ ThreadPool.getInstace.excute(new Runnable{ @override public void run(){ write(data.getBytes());(3) } }); }

这是一段很简单的代码,就是通过线程池发送了两个消息,首先发送 “stop”消息,然后再发送一个 “play” 消息。 但是执行的结果却 出乎意料,因为这两消息的执行顺序非常随机,有时先执行“stop” 消息,然后再执行 “play” 消息,有时刚好相反,问题究竟出在哪里呢?

首先我们要明白,exeTask() 方法中的的两行代码(1),(2)是在同一个 线程中执行的,假设都是 主线程(main Thread)。

sendData() 中的代码是在 线程池中 执行 的,即(3)这行代码是在子线程中执行的。

3.多线程其实是一个伪概念,程序真正执行时还是单线程执行的,所谓的多线程只不过是 cpu 在 多个 线程间切换执行,每个线程执行一定的 时间片后然后切换。理解了这一点后,那么上面的代码就会出现下面几种可能:

1> 代码(1)先调用,但是主线程的时间片还未结束,于是代码(2)调用,主线程执行完毕,然后才开始两个子线程抢占,随机执行 2> 代码(1)先调用,但是主线程的时间片到了,于是切换到(1)代码中的子线程执行去发送数据,执行完毕后,又切换到主线程执行,开始执行代码(2),然后执行代码(2)的发送数据

第二种可能才是我们想要的结果,但是第一种可能却是多线程无法避免的问题,那该怎么解决这样的问题呢? 对 sendData() 稍作修改: /* * 通过handler 消息队列发送消息,(当然采用HandlerThread) */ public void sendData(final String data){ handle.post(new Runnable{ @override public void run(){ write(data.getBytes()); } }) }

通过消息队列,消息依次入列,即可以在子线程依次将消息发送出去。。。

转载请注明原文地址: https://www.6miu.com/read-2619804.html

最新回复(0)