美文网首页
ThreadPoolExecutor 死锁问题总结

ThreadPoolExecutor 死锁问题总结

作者: AndroidHint | 来源:发表于2017-07-23 22:10 被阅读0次

    发现问题

    在项目中做一个发送多张图片到服务器的功能,在发送前要将图片进行压缩并保存,然后拿到保存后的路径进行图片的上传。问题就出现在压缩的过程中,压缩的操作步骤如下:

    1、检查是否有PNG格式的图片,如果有则将PNG转换成JPG格式,转换过程使用了一个线程去执行,这里记为线程A,转换成功后跳到步骤2。如果没有PNG格式的图片,则直接跳到步骤2。

    2、我们需要将所有的JPG格式进行压缩,我们优先使用云通信提供的方法进行压缩,压缩过程使用了一个线程,这里记为线程B。如果全部图片压缩成功,则返回压缩成功,将图片上传到服务器。否则,使用云通信的方法压缩失败,我们将压缩失败的图片添加到一个集合中,使用另外一种压缩方法(这种方法压缩率比较高,但是也失真不少)进行失败图片的压缩,这里记为线程C,压缩成功返回并上传图片到服务器,压缩失败则提示压缩失败。

    所以我们这里分为四种情况:

    第一种情况:

    有PNG格式的图片,使用云通信压缩成功。则线程A执行,在线程A内部再执行线程B。

    第二种情况:

    有PNG格式的图片,使用云通信压缩未能成功。则线程A执行,在线程A内部再执行线程B,在线程B内部再执行线程C。

    第三种情况:

    没有PNG格式的图片,使用云通信压缩成功。则线程B执行。

    第四种情况:

    没有PNG格式的图片,使用云通信未能压缩成功。则线程B执行,在线程B内部再执行线程C。

    问题的发生就出现在线程的内部嵌套,而我们只使用了一个ThreadExcetor来管理线程。至此,我们将上述的四种情况中的第三种情况排除(没有线程的嵌套),只讨论其余三种情况。

    分析问题

    为了简单起见,我们就拿第一种情况来分析。对于嵌套线程,线程A执行时,实际上是向线程池中添加了三个任务,其中线程A是主任务,线程B和线程C是子任务。当线程A占用了线程池的资源后,线程B和线程C就阻塞了,而线程B和线程C的执行要等到线程池中资源的释放,而线程池资源的释放要等到线程A的执行完毕,线程A的执行完毕要等线程B和线程C执行完毕。这样就进入了死锁的状态。

    解决问题

    将多线程变成单线程,例如对于第一种情况,我们可以只建立线程A,然后在线程A执行的过程中不要创建线程B和线程C,而是让线程B和线程C的操作继续使用线程A来执行,这样就不会出现线程的嵌套问题了,也就防止了死锁。

    相关文章

      网友评论

          本文标题:ThreadPoolExecutor 死锁问题总结

          本文链接:https://www.haomeiwen.com/subject/dhepkxtx.html