这里我有一个有两个可以访问List的线程的类。一个线程定期用更新的副本替换列表,另一个线程将列表的内容绘制到屏幕上。
for var i=0; i<items.count; ++i
{
if let idDict = items[i]["id"] as? NSDictionary
{
let id = idDict["videoId"] as! String
//self.videoId = [id]
self.videoId.append(id)
}
}
print(self.videoId)
我的问题是,我是否需要同步访问dataList?我应该怎么做呢?这会有用吗?
public class ThreadSafePainter {
private List<String> dataList = new ArrayList<>();
/*
* starts a thread to periodically update the dataList
*/
public ThreadSafePainter() {
Thread thread = new Thread(() -> {
while (true) {
// replace out-dated list with the updated data
this.dataList = getUpdatedData();
// wait a few seconds before updating again
Thread.sleep(5000);
}
});
thread.start();
}
/*
* called 10 times/second from a separate paint thread
* Q: Does access to dataList need to be synchronized?
*/
public void onPaint(Graphics2D g) {
Point p = new Point(20, 20);
// iterate through the data and display it on-screen
for (String data : dataList) {
g.drawString(data, p.x, p.y);
p.translate(0, 20);
}
}
/*
* time consuming data retrieval
*/
private List<String> getUpdatedData() {
List<String> data = new ArrayList<>();
// retrieve external data and populate list
return data;
}
}
答案 0 :(得分:1)
任何时候你有多个线程访问相同的可变状态(好吧,几乎任何时候,都有一些例外,比如当你知道状态在另一个线程的生命周期内不会发生变异时),你需要采取一些类型的动作。在这种情况下,您正在改变字段dataList
,并且您希望另一个线程对此作出反应。所以,你需要做一些事情&#34;。最通用的解决方案是使用synchronized
,你的大纲如何做到这一点就好了。
如果你想使用某种东西来挤压最大性能(这对于GUI问题来说有点荒谬),或者你想展示你对并发性的深刻理解,你可以考虑更多适用于更多的轻量级替代品有限的情况。在这种情况下,您只有一个编写器,编写器只编写一个引用。对于这种情况,volatile
就足够了。在这种代码中,我个人只会坚持使用synchronized
,因为在更改代码时它不太可能中断,就像你可能添加另一个编写器线程一样。
答案 1 :(得分:0)
如果您没有使列表同步,那么您应该使List易失。这样读取线程就可以获得List变量值的最新副本。
Here是一个很好的解释。
答案 2 :(得分:-1)
官方Java-Documentation指出,ArrayList未同步。所以你需要同步它。
但是文档还说这只适用于多个线程访问同一个列表的情况。所以在你的情况下,没有必要同步它。但是如果你想100%确定你可以通过这个简单的电话同步你的List:
List<data_type> list = Collections.synchronizedList(new ArrayList<data_type>());
...其中“data_type”是您要存储的类型值。