3个线程,可以访问java中的1个对象

时间:2013-10-15 14:13:59

标签: java multithreading

我想为3个线程之间的通信创建一个静态arrayList: 1.线程会将一些数据添加到列表中; 2.线程将从列表中删除数据; 3.线程(每3秒一次计时器)将检查列表大小是否等于0,如果没有打印该列表的所有对象。

我很想知道如果超过1个线程会同时尝试访问此列表会发生什么(例如,当第二个线程将从列表中删除对象时,计时器将同时检查列表的大小)。 我想我必须同步这个列表,但不知道该怎么做。你能给我一些建议吗?

5 个答案:

答案 0 :(得分:3)

  

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

首先ArrayList 不是线程安全的 ,因此您不应直接使用它。

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

您的要求似乎与Queue类似,因此您应该使用BlockingQueue,例如线程安全的LinkedBlockingQueue

注意:

如果您使用Collections.synchronizedList(...),则列表中的复合操作仍然不安全。

答案 1 :(得分:2)

您可以使用

List myList = Collections.synchronizedList(new ArrayList());

答案 2 :(得分:2)

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

根据相关问题的建议:How do I make my arraylist thread safe您可以使用Collections.synchronizedList(...)获取List的线程安全版

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中删除数据。

答案 3 :(得分: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
}

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

答案 4 :(得分:1)

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

在打印线程中:

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

在编辑列表的线程中:

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

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