0

I want to create a static arrayList for communication between 3 threads: 1. thread will add some data to list; 2. thread will remove data from list; 3. thread (timer every 3 sec) will check if size of list equals 0, and if no print all object of this list.

I'm wondereing what would happen if more than 1 thread will try to access this list at same time (for example timer will check size of list at same time when second thread will be removeing object from list). I guess that i have to synchronize this list, but have no idea how to do that. Can you give me some advise?

4

5 回答 5

3

我想知道如果超过 1 个线程同时尝试访问此列表会发生什么

首先ArrayList不是线程安全的,所以你不应该直接使用它。

一种可能性是使用Collections.synchronizedList(...);它为您提供线程安全但会妨碍并发性。

您的要求似乎就像 a Queue,所以您应该使用BlockingQueue它,例如LinkedBlockingQueue它是线程安全的。

笔记:

如果你使用 list 上的复合操作仍然是不安全Collections.synchronizedList(...)的。

于 2013-10-15T14:17:30.873 回答
2

您可以使用

List myList = Collections.synchronizedList(new ArrayList());
于 2013-10-15T14:16:49.747 回答
2

ArrayList不是线程安全的。您需要自己处理同步,否则结果将不可预测。

正如相关问题中所建议的:How do I make my arraylist thread safe you can use Collections.synchronizedList(...)to get a thread-safe version of yourList

javadoc 给出了如何利用该List方法返回的示例。

List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());
} 

其他解决方案已经提出了这一点,但使用这种方法可能会降低性能,因为同步会阻止对List. 这最终将限制您从支持中添加和删除数据的速率List

于 2013-10-15T14:17:11.093 回答
1

此代码段将帮助您朝着正确的方向前进

//have a lock Object
private static final Object lock = new Object();
// your list
private static List list = null

//synchronized on lock object. this will allow only one thread at a time
synchronized(lock){
//access,add to, remove from list
}

通过这种方式,您可以确保一次只有一个线程访问您的列表

于 2013-10-15T14:19:01.293 回答
1

更好的是,使用并发原语(等待、通知和同步),您可以让打印线程等待,并且只有在其他线程之一实际更改 ArrayList 后才唤醒。这样做的好处是在没有变化时不打印,并在发生变化时立即唤醒。您可能仍然会得到错误的唤醒,但如果这是一个问题,可以对其进行编码。

在打印线程中:

synchronized(lock)
{ 
    while(true/*or some boolean to indicate you're done*/)
    {
        lock.wait();
        //print list
    }
}

在编辑列表的线程中:

synchronized(lock)
{
    //modify list
    lock.notify();
}

lock.wait(3000);即使没有发生任何变化,您也可以在 3 秒后打印。

于 2013-10-15T14:32:03.483 回答