解决的几个多线程的Case

最近做过几个Case,都是因为多线程而造成的BUG。

1. ArrayList是非线程安全的,程序将会去读配置文件并将获取的信息放置到一个静态ArrayList中。如果这个ArrayList不为空,则会直接返回。现在有一个线程在ArrayList为空的时候进入了读取配置的操作中并不停的向ArrayList中添加数据,而另外一个线程则判断ArrayList已经不为空,则直接返回了。之后这个ArrayList会做为

参数来new一个新的ArrayList,这时候错误发生了。

我们可以看:

    public ArrayList(Collection<? extends E> c) {
        size = c.size();
        // Allow 10% room for growth
        int capacity = (int) Math.min((size*110L)/100, Integer.MAX_VALUE);
        elementData = (E[]) c.toArray(new Object[capacity]);
    }

 

 public <T> T[] toArray(T[] a) {
        if (a.length < size)
            a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

其实在toArray(T[] a)方法中已经为了保险起见,判断了数组的长度,如果小的话,会重建一个新的数组。However,实际上就在执行copy方法之前,size还是由于另外一个线程还在添加新的信息又发生了改变,所以ArrayIndexOutOfBoundsException还是被抛出了。

在使用这非线程安全的容器是还是应该多长几个心眼的,这样能尽量避免这些问题的出现。

 

2. 这是一个关于WebsphereMQ 的 messageID的问题,我们的Exception处理中包含这么一个逻辑,一个被定义为Level A的Exception,抛出后会把消息backout回MQ里以便可以后续处理,5次重试后,就会变成Level B的Exception并将信息持久化到数据库里,并把消息继续backout,但是会把这个消息的messageID存入到HashMap里面。读消息的时候会判断这个HashMap,如果这个messageID被存入了,则不会做任务处理,把MQ commit掉。

然而诡异的事情发生了,不该commit的消息commit掉了,但是没做任何正常处理,而出错的消息却又做了一遍,继续抛出level B的exception。

首先我们想到的是HashMap是一个非同步的对象,这样会出错吗?

我们仔细研究了JDK源代码,正如我们所理解的,被HashMap认为是相同的key必须满足hashcode和equals()方法一样,对于String对象而言,这个完全是不可能的。为了确信,这时候我们写了测试方法,启动了几个线程来向HashMap中不停的插入或删除键值,但是我们保证key值是都不一样的String,结果一切都很正常。

难道MessageID出现了重复,我又查看了IBM相关的资料,MessageID是按照一定的规则的产生,并且会保证唯一。当我们enqueue的时候保证messageID为空或者MQPutMessageOptions设置了选项MQC.MQPMO_NEW_MSG_ID的时候,WebsphereMQ理论上会给我们生成唯一的MessageID。

终于,谜底解开了,WebsphereMQ的JavaAPI给我们返回的是MessageID是byte数组,而代码直接使用new String(byte[])来转化成String。这样Java会采用系统默认的编码来转化。我的机器默认是GBK,而美国Soloris服务器则是使用美国本地的编码。就这样,我们可以看到,每个byte若为负,转化后到变成了63,也就是?号。所以出现了很多重复的ID,也就导致系统丢失该处理message。这时我们只需要采用ISO-8859-1来转成String就不会有任何的问题。

 

3.还有几个问题,基本上和1描述的差不多,都是因为多线程或是不同的服务器操作同样的资源而导致了BUG。

 

多线程一直会是一个困扰人的问题,编程的时候应该多考虑考虑,尽量避免出错。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值