java - 在多线程中维护Arraylist的顺序

标签 java multithreading

当使用两个线程时,如何确保打印输出顺序与原始数组中的顺序相同?我希望它打印“0 1 2 3 4 5 6 7 8 9”,但目前无法保证顺序。有什么办法可以让它有序吗?万分感谢。

public class Test {
    public static void main(String[] args){
        DataStore dataStore = new DataStore();
        for(int i=0; i<10; i++){
            dataStore.add(String.valueOf(i));
        }
        CopyThread t1 = new CopyThread(dataStore);
        CopyThread t2 = new CopyThread(dataStore);
        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch(Throwable t) {
        }
    }   
}

class CopyThread extends Thread {
    private DataStore data; 

    public CopyThread(DataStore data){
        this.data = data;
    }
    public void run(){      
        DataStore.Line line = null;
        int lineID;

        while( (line = data.getLine()) != null ){       
            lineID = line.id;       
            System.out.println(Thread.currentThread().getName() + ": " + lineID);       
        }   
    }
}

class DataStore {
    ArrayList<String> lines = new ArrayList<String>();
    int current = 0;

    public synchronized Line getLine () {
        if (current >= lines.size()) {
            return null;
        }
        Line line = new Line(lines.get(current), current);
        current++;

        return line;
    }

    public synchronized void add (String s) {
        lines.add(s);
    }

    public synchronized int size () {
        return lines.size();
    }

    public static class Line {
        public String line;
        public int id;

        public Line (String str, int i) {
            line = str;
            id = i;
        }
    }
}

最佳答案

尝试使用 Vector 而不是 ArrayList 。

Vector

The Vector class implements a growable array of objects. Like an array, it contains components that can be accessed using an integer index. However, the size of a Vector can grow or shrink as needed to accommodate adding and removing items after the Vector has been created.

Each vector tries to optimize storage management by maintaining a capacity and a capacityIncrement. The capacity is always at least as large as the vector size; it is usually larger because as components are added to the vector, the vector's storage increases in chunks the size of capacityIncrement. An application can increase the capacity of a vector before inserting a large number of components; this reduces the amount of incremental reallocation.

The Iterators returned by Vector's iterator and listIterator methods are fail-fast: if the Vector is structurally modified at any time after the Iterator is created, in any way except through the Iterator's own remove or add methods, the Iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the Iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future. The Enumerations returned by Vector's elements method are not fail-fast.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

关于java - 在多线程中维护Arraylist的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15997113/

相关文章:

java - 切换 fragment 后Android应用程序崩溃

java - 如何使用 Jodatime 转换年、月、日中的天数?

ruby - (J)Ruby - 杀死一个线程可以吗?

c# - 定时器类在程序结束前不触发

java - 使用 rabbitmq 了解 spring cloud 消息传递

java - 数组排序与并行排序性能比较

java - 使用 Docker Compose 连接到另一个容器中运行的 mysql

c++ - 如何使一个线程 "promptly"中的内存存储在其他线程中可见?

c++ - 如何重新启动崩溃的线程

c# - 几个小时后并行发送 HTTP 请求后 ServicePoint 对象的大小很大