图11 崩溃子线程堆栈信息二
通过子线程堆栈信息的分析,我们发现在崩溃日志中除了主线程以外,还有另外两个子线程也停留在获取系统剪贴板UIPasteboard对象的操作中。其中有一个线程停留在 [WBWMDA_OpenUDID valueWithError:]方法中,查看他的实现后发现这是应该另一个私有化的OpenUDID代码,同样维持了OpenUDID原有的逻辑:循环100次尝试获取名称从org.OpenUDID.slot.0到org.OpenUDID.slot.99的UIPasteboard对象,从中获取openudid的值。由于它是在子线程中被调用的,就导致了子线程频繁获取UIPasteboard对象的情况。
子线程反复调用UIPasteboard的接口会使App卡主吗?接下来,我们再验证一下子线程操作UIPasteboard对象的情况:
验证子线程调用UIPasteboard的影响
图12 子线程UIPasteboard测试代码
如上图所示,将之前100次的UIPasteboard操作放在子线程中,执行后App成功启动,并得到如下输出:
图13 子线程UIPasteboard测试代码执行输出结果
从结果中可以看出,将上述复杂的UIPasteboard操作放入子线程的确可以使App启动,且对UIPasteboard的操作耗时与在主线程中是一致的。也并未阻塞App启动,反而很顺利地进入了测试Demo的首页。
由此可以看出单单在子线程反复调用剪贴板的逻辑并不会使App卡主。那么主线程与子线程同时调用UIPasteboard会有什么影响呢?继续测试
主线程与子线程同步频繁调用UIPasteboard接口测试
图14 主线程与子线程混合UIPasteboard测试代码
同时开启主线程和子线程来执行多次UIPasteboard操作,其中主线程执行50次,子线程执行50次。在最开始的测试中,在主线程进行100次UIPasteboard操作耗时一共50秒,现在我们将其中的一般转移到了子线程那么耗时应该减少一半。是这样吗?执行代码验证一下,输出如下: