Java MultiThreading行为说明 [英] Java MultiThreading behaviour explanation

查看:87
本文介绍了Java MultiThreading行为说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习Java多线程.我写了一小段代码,并得到一些我听不懂的输出.请提供一些解释. 在下面发布代码.

I am learning Java multithreading. I wrote a small piece of code and results in some output which i am not able to understand..please help with some explanation. Posting the code below.

package com.java.learn;

import java.util.ArrayList;
import java.util.List;

public class ListTestWithMultiThread {
    static final List<Integer> list = new ArrayList<Integer>();

    public static void main(String[] args) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 100; i++) {
                    list.add(Integer.valueOf(i));
                }
                System.out.println("List size at thread 0 : " + list.size());
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 101; i <= 200; i++) {
                    list.add(Integer.valueOf(i));
                }
                System.out.println("List size at thread 1 : " + list.size());
            }
        }).start();
    }
}

各种运行中的一些o/p: 线程0的列表大小:134 线程1的列表大小:200

Some of the o/p in various runs: List size at thread 0 : 134 List size at thread 1 : 200

Exception in thread "Thread-1" List size at thread 0 : 101
java.lang.ArrayIndexOutOfBoundsException: 17
    at java.util.ArrayList.add(Unknown Source)
    at com.java.learn.ListTestWithMultiThread$2.run(ListTestWithMultiThread.java:25)
    at java.lang.Thread.run(Unknown Source)

    List size at thread 0 : 106
Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 58
    at java.util.ArrayList.add(Unknown Source)
    at com.java.learn.ListTestWithMultiThread$2.run(ListTestWithMultiThread.java:25)
    at java.lang.Thread.run(Unknown Source)

推荐答案

您正在访问的数据结构(list)不是为并行访问而设计的,而没有保护(例如通过synchronized).最终将破坏数据结构的内部结构,导致出现奇怪的行为,如您得到的异常.

You are accessing an data-structure (the list) that is not designed for concurrent access in parallel without protecting it (e.g. via synchronized). This will eventually corrupt the internals of the data-structure leading to weird behavior like the exception you get.

以下是两种处理方法:

  1. 使用并发数据结构:

List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());

  1. 使用synchronized保护列表:

synchronized(list) {
      list.add(Integer.valueOf(i));
}

编辑:自从您提出要求以来,这就是ArrayList损坏的方式. ArrayList由数组支持,当列表增长时,该数组必须重新调整大小.在此处调整大小意味着分配了一个更大的新数组,并将旧数组的内容复制到了新数组中.这是

Edit: Since you asked for it, here is how the ArrayList can get corrupted. An ArrayList is backed by an array that has to be resized when the list grows. Resizing here means an new, larger array is allocated and the content of the old one copied to the new one. Here are parts of the code that does that:

int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
...
elementData = Arrays.copyOf(elementData, newCapacity);

现在想象一下:线程A开始调整数组的大小,它计算新的容量并开始在第4行中复制数据.但是,在它可以将新数组的引用复制到elementData之前,由于某种原因,它会停止(这事儿常常发生).现在,线程B开始调整数组的大小并完成操作.然后,它将更多的值插入到列表中,并再次调整数组的大小并完成操作.现在,线程B假定该列表足够大,可以容纳一个新值,但是在它插入该值之前,线程A会醒来并使用对它创建的较小数组的引用覆盖elementData.现在,线程B尝试将值插入较小的数组并获得ArrayIndexOutOfBoundsException.这一切都是不太可能的,但您可能会看到.

Now imagine the following: Thread A start resizing the array, it computes the new capacity and starts copying the data in line 4. But before it can copy the reference of the new array to elementData it gets stoped for whatever reason (this happens all the time). Now Thread B starts resizing the array and finishes. Then it inserts more values into the list and resizes the array again and finishes. Thread B now assumes that the list is large enough for a new value, but before it inserts the value, thread A wakes up and overrides elementData with the reference to the smaller array it has created. Thread B now tries to insert a value into the smaller array and gets an ArrayIndexOutOfBoundsException. This all is kinda unlikely but it can happen as you see.

这篇关于Java MultiThreading行为说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆