多线程使我们的程序的执行效率得到了很大的提高,但稍有不慎,它也给我们程序带来致命一击,下面就通过一段伪代码来解析平时容易犯错误的一个问题,代码如下:
/**
* 执行一个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());
}
})
}
通过消息队列,消息依次入列,即可以在子线程依次将消息发送出去。。。