很多问题,自己测试可能测不出来,但是跑到了线上,就有可能出现问题,比如多线程问题。

错误堆栈:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0at java.util.ArrayList.get(ArrayList.java:437)at com.zhangyue.we.ad.model.AdSchedule.getValidPartnersAdSource(SourceFile:347)at com.zhangyue.module.ad.e.isPartnersAdTimeOn(SourceFile:177)at com.zhangyue.module.ad.e.processEvent(SourceFile:50)at com.zhangyue.iReader.module.driver.ad.a.loadAdStrategy(SourceFile:324)at com.zhangyue.iReader.module.proxy.AdProxy.loadAdStrategy(SourceFile:72)at com.chaozh.iReader.ui.activity.u.run(SourceFile:689)at java.lang.Thread.run(Thread.java:764)

有问题的代码:


public class AdSchedule {private ArrayList<String> mAdResource;public boolean hasValidAd(String pos) {if (!isHaveRules()) {return false;}ArrayList<Bean> beans = body.rule.get(pos);if (beans != null) {mAdResource = new ArrayList<>();mAdResource.clear();for (Bean bean : beans) {if (bean.isValid()) {mAdResource.add(bean.source);return true;}}}return false;}** @param pos 广告显示的位置* @return*/public String getValidPartnersAdSource(String pos) {if (!isHaveRules()) {return "";}ArrayList<Bean> beans = body.rule.get(pos);if (beans != null) {mAdResource = new ArrayList<>();mAdResource.clear();int apkVersionCode = APK.getApkVersionCode(PluginRely.getAppContext());if (Util.isRunningInVivo(PluginRely.getAppContext()) && apkVersionCode >= 7150005 && apkVersionCode != 7150009) {for (Bean bean : beans) {if (bean.isValid()) {mAdResource.add(bean.source);LOG.E(TAG, "Ad插件配置的广告资源 source : " + bean.source);}}StringBuilder result = new StringBuilder();for (int i = 0; i < mAdResource.size(); i++) {result.append(mAdResource.get(i));if (i != mAdResource.size()-1) {result.append("|");}}return result.toString();}else {for (Bean bean : beans) {if (bean.isValid()) {mAdResource.add(bean.source);LOG.E(TAG, "Ad插件配置的广告资源 source : " + bean.source);return bean.source;}}}}return "";}/*** 获取当前要显示的广告资源。返回的是排期中第一个广告资源** @return*/@JSONField(serialize = false)public String getAdResource() {if (mAdResource != null && mAdResource.size() > 0) {String source = mAdResource.get(0);return TextUtils.isEmpty(source) ? "三方广告" : source;} else {return "三方广告";}}}

修改之后:

/*** @description*/
public class AdSchedule {public final static String TAG = "ad_AdSchedule";public int code;public String msg;public BodyBean body;// 仅标识开屏位置的广告源private ArrayList<String> mAdResource;** @param pos 广告显示的位置* @return*/public String getValidPartnersAdSource(String pos) {if (!isHaveRules()) {return "";}ArrayList<Bean> beans = body.rule.get(pos);if (beans != null) {List<String> adResource = new ArrayList<>();//vivo 项目 该方法返回一个列表  里面有广告补量的逻辑,如果第一个广告展示不了,加载第二个,只在vivo 7.15.5以上版本返回,7.15.9上不返回,因为7.15.9是7.15.3的复制品int apkVersionCode = APK.getApkVersionCode(PluginRely.getAppContext());if (Util.isRunningInVivo(PluginRely.getAppContext()) && apkVersionCode >= 7150005 && apkVersionCode != 7150009) {for (Bean bean : beans) {if (bean.isValid()) {adResource.add(bean.source);LOG.E(TAG, "Ad插件配置的广告资源 source : " + bean.source);}}StringBuilder result = new StringBuilder();for (int i = 0; i < adResource.size(); i++) {result.append(adResource.get(i));if (i != adResource.size()-1) {result.append("|");}}return result.toString();}else {for (Bean bean : beans) {if (bean.isValid()) {adResource.add(bean.source);LOG.E(TAG, "Ad插件配置的广告资源 source : " + bean.source);return bean.source;}}}}return "";}/*** 获取当前要显示的广告资源。返回的是排期中第一个广告资源** @return*/@JSONField(serialize = false)public String getAdResource() {if (mAdResource == null) {if (isHaveRules()) {ArrayList<Bean> beans = body.rule.get(Const.POS_SPLASH);if (beans != null) {mAdResource = new ArrayList<>();for (Bean bean : beans) {if (bean.isValid()) {mAdResource.add(bean.source);}}}}}if (mAdResource != null && mAdResource.size() > 0) {String source = mAdResource.get(0);return TextUtils.isEmpty(source) ? "三方广告" : source;} else {return "三方广告";}}
}

错误原因:

这个mAdResource 在多个方法里面都有赋值操作,如果在一个方法里面正在遍历,另一个方法里面直接清楚了,那么就会发现数组越界异常。
大家最好在自己方法里面,单独赋值给一个局部变量,然后对局部变量进行操作。或者加上锁。

比如一下代码,把ma 赋值给局部变量a,然后对a 进行操作,就不会有多线程问题。

Object a = ma;
a.setValue

错误堆栈:

java.lang.IllegalThreadStateExceptionat java.lang.Thread.start(Thread.java:724)at com.zhangyue.ireader.zyadsdk.comm.managers.n.b(SourceFile:101)at com.zhangyue.ireader.zyadsdk.comm.managers.n.preLoadVideoMaterial(SourceFile:86)at com.zhangyue.iReader.module.driver.ad.a.loadAdStrategy(SourceFile:334)at com.zhangyue.iReader.module.proxy.AdProxy.loadAdStrategy(SourceFile:72)at com.zhangyue.iReader.module.idriver.ad.AdUtil.updateAdSchedule(SourceFile:33)at com.zhangyue.iReader.free.FreeModelReceiver.onReceive(SourceFile:41)at android.support.v4.content.LocalBroadcastManager.executePendingBroadcasts(SourceFile:313)at android.support.v4.content.LocalBroadcastManager$1.handleMessage(SourceFile:121)at android.os.Handler.dispatchMessage(Handler.java:106)at android.os.Looper.loop(Looper.java:224)at android.app.ActivityThread.main(ActivityThread.java:7073)at java.lang.reflect.Method.invoke(Native Method)at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:928)

有问题的:

 private void initHandler() {if (mHandlerThread == null) {mHandlerThread = new HandlerThread("LoadVideoMaterial", Process.THREAD_PRIORITY_BACKGROUND);mHandlerThread.start();}

修改之后:

    private synchronized void  initHandler() {if (mHandlerThread == null) {mHandlerThread = new HandlerThread("LoadVideoMaterial", Process.THREAD_PRIORITY_BACKGROUND);mHandlerThread.start();}

原因:

因为这个方法可能会把多个线程调用,所以,只是判空不能解决多线程的问题。所以,保险起见,所有被多个线程调用的地方,都要做
多线程处理。尤其是线程启动这种,只能调用一次的地方。

总结:

1. 变量在多个方法都有操作,容易多线程异常
2. 最好赋值给一个新的本地变量。
3. 线程开启问题,线程启动最好都有多线程处理。

Java 代码多线程问题相关推荐

  1. Java实现多线程远程投屏并打包可执行文件(从代码到.exe)

    Java实现多线程远程投屏并打包可执行文件(从代码到.exe) 前言 原理 成品展示 代码实现 客户端 生成询问框 询问框选择响应 截取输入字符串 与服务端建立联系 创建数据输入流 创建窗口及面板 获 ...

  2. Java中多线程、多线程的实现方式、同步代码块的方式

    多线程 进程 线程 概念 目前的程序是单线程 线程的组成部分 代码实现多线程的方式 第一种方式 第二种方式 第三种方式 -- 线程池 第四种方式:Callable 线程状态 线程同步 临界资源 原子操 ...

  3. java实现多线程抢单_Java模拟多线程实现抢票代码实例

    这篇文章主要介绍了Java模拟多线程实现抢票,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 实现100张票抢购的demo 这里需要一个变量,来保存1 ...

  4. 【多线程高并发】查看Java代码对应的汇编指令教程

    1.首先下载hsdis-amd64.dll文件 零积分下载地址:https://download.csdn.net/download/Kevinnsm/54740576 2.解压放到java11\bi ...

  5. 厚积薄发打卡Day25 :狂神说Java之多线程详解<全网最全(代码+笔记)>

    概述 视频来源:[狂神说Java]多线程详解 强烈推荐,

  6. Java 并发/多线程教程(四)-并发模型

    本系列译自jakob jenkov的Java并发多线程教程(本章节部分内容参考http://ifeve.com/并发编程模型),个人觉得很有收获.由于个人水平有限,不对之处还望矫正! 并发系统可以有多 ...

  7. LeetCode1117. Building H2O --Java解法--多线程保证执行顺序--AtomicInteger

    此文首发于我的个人博客:LeetCode 1117. Building H2O --Java解法–多线程保证执行顺序–AtomicInteger - zhang0peter的个人博客 LeetCode ...

  8. java mina多线程_Java多线程基础总结九:Mina窥探(1)

    一直以来的多线程的基础总结都是脱离应用的,但是要说多线程的应用就不能不说Mina.Apache Mina作为一个高性能的Java异步并发网 络通讯框架,其内部的多线程的设计和实现可谓是学习多线程的良药 ...

  9. Java接口多线程并发测试 (一)

    本文为作者原创,禁止转载,违者必究法律责任!!! 本文为作者原创,禁止转载,违者必究法律责任!!! Java接口多线程并发测试 一,首先写一个接口post 请求代码: import org.apach ...

最新文章

  1. 我为什么要做游戏化教养项目
  2. 使用EasyUI的Datagrid的Editor进行行编辑,Enter回车结束编辑,并开启新的一行。
  3. 玩转12306之系统登录
  4. centos8 默认nginx路径_CentOS 8系统安装Nginx Web服务器及常见配置过程
  5. 【论文复现】Character-level Convolutional Networks for Text Classification
  6. 支持 RISC-V 芯片的 Android 系统来了!
  7. [Flex] flex的安全沙箱,你保障了安全的同时也害苦了多少我这样的人那
  8. java sqlserver数据库连接_JAVA连接SQLserver数据库
  9. Android截图-截屏与截长图(二)
  10. mac安装maven
  11. 配置文件 ini toml yaml 以及 json对比
  12. RtlUnicodeStringToAnsiString中第三个参数引发的bsod
  13. 【COS】函数使用技巧
  14. 面试之防火墙软硬件架构
  15. linux系统课程ubuntu视频教程
  16. poj3347——正方形覆盖(区间覆盖)
  17. 阴历转阳历java_GitHub - opprime/calendarist: 一个可实现阳历、阴历、干支历间相互转换的JAVA工具...
  18. GUI(Graphical User Interface)
  19. 国家计算机报名730,730分学霸杨晨煜被清华智班录取!学习的专业是......
  20. tuxera NTFS2022让磁盘读写管理格式化更轻松

热门文章

  1. java mybatis enum_mybatis处理枚举类的简单方法
  2. python爬微博关键字_一个简单的python爬虫实践,爬取包含关键词的新浪微博
  3. 开闭操作进行平滑处理与边缘提取
  4. python基础学习语法和函数
  5. sqlserver 无法远程连接到服务器,SQLServer2019无法连接远程服务器
  6. python环境变量配置_python+ pycharm 环境安装 + pycharm使用
  7. c# 可选参数与命名实参
  8. ORACLE 配置文件
  9. Struts2教程2:处理一个form多个submit
  10. (一)SOA学习-相关缩写