欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-15 15:22:52
...
多线程使我们的程序的执行效率得到了很大的提高,但稍有不慎,它也给我们程序带来致命一击,下面就通过一段伪代码来解析平时容易犯错误的一个问题,代码如下:
/**
*  执行一个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” 消息,有时刚好相反,问题究竟出在哪里呢?

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

  2. 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());
        }
    })
}

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

相关标签: 多线程