Java Android runOnUiThread线程安全
我想知道我处理特定问题的方法是否是线程安全的(可能不是,这就是我问的原因)。假设我们在非UI线程上运行以下代码:Java Android runOnUiThread线程安全,java,android,concurrency,Java,Android,Concurrency,我想知道我处理特定问题的方法是否是线程安全的(可能不是,这就是我问的原因)。假设我们在非UI线程上运行以下代码: if (myMap != null) { runOnUiThread(new Runnable() { @Override public void run() { Something something = myMap.get(someKey); // update some
if (myMap != null)
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Something something = myMap.get(someKey);
// update some views and stuff
}
});
}
我猜我不能保证在runnable实际执行时myMap是有效的,对吗?如果是这种情况,我是否应该移动myMap!=run()方法内部为null,还是在那里复制它?如果我想确保runOnUiThread代码仅在映射不为null时执行,那么最好的方法是什么
谢谢这很简单,只需在执行您给出的代码之前定义myMap即可:
Map<String, String> myMap = new Hashmap<String, String>();
//if (myMap != null)
// {
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Something something = myMap.get(someKey); //myMap won't be null
// update some views and stuff
}
});
// }
这与在执行您给出的代码之前定义myMap一样简单:
Map<String, String> myMap = new Hashmap<String, String>();
//if (myMap != null)
// {
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Something something = myMap.get(someKey); //myMap won't be null
// update some views and stuff
}
});
// }
创建Runnable并将其传递给函数“runOnUiThread()”时,如果当前线程是主线程,则将立即执行该线程,或者将其放入队列并稍后执行,此时该对象可能无效。最好是在工作线程中检查其有效性(在Runnable的run()方法中)。当您创建Runnable并将其传递给函数“rununuithread()”时,如果当前线程是主线程,则将立即执行该线程,或者将其放入队列中并稍后执行,此时该对象可能无效。如果您在工作线程(Runnable的run()方法)中检查它的有效性会更好。您的一般结构不是线程安全的 启动整个进程的线程检查
myMap
,并在另一个线程中启动执行
if (myMap != null) {
doSomethingInAnotherThread();
}
// something can set `myMap` to null here...
计划运行的代码将在某个时候运行
void inAnotherThread() {
myMap.access();
}
但是不能保证myMap
与以前一样。如果有线程可以更改myMap
所指的内容,则执行以下操作
void inAnotherThread() {
if (myMap != null) {
myMap.acess();
}
}
仍然不是线程安全的,因为您访问myMap
两次,每次都可能不同。例如,if
中的值不为空,但一旦您访问该值,该值即为null
。一种解决方案是复制引用,以便在使用该引用时,任何内容都不能更改该引用的本地副本
void inAnotherThread() {
Map localReference = myMap;
if (localReference != null) {
localReference.acess();
}
}
这是否是线程安全取决于myMap
。例如,它是否为易变的(或是最终的)。如果是:其他线程保证看到myMap
引用的最新版本,如果不是:不保证。(注意:我认为runOnUiThread
建立了一个“发生在之前”的关系,因为它在内部同步,因此您应该有某种程度的保证可以看到引用的最新版本)
一旦您有了对正确的Map
实例的引用,下一点就是您可以安全地使用它。简单的HashMap
使用起来不是线程安全的。如果您调用.get()
它仍然可能在您身上爆炸,如果同时另一个线程调用put
/remove
/。。因此在.get
访问数据时会更改数据
您可以将它包装在集合中。synchronizedMap(map)
将使等单个操作成为原子操作,以便其他线程不会干扰。但它仍然不是每件事都是线程安全的。例如,如果不进行外部同步,迭代值仍将失败。这个问题可以通过使用同样支持迭代的ConcurrentHashMap
来解决
线程安全性取决于许多因素以及您对什么是线程安全的定义。如果您可以保证myMap
设置为,则您编写的内容已经是线程安全的null
并且您知道后台线程已完成修改myMap
,因此UiThread访问它是安全的。您的一般结构不是线程安全的
启动整个进程的线程检查myMap
,并在另一个线程中启动执行
if (myMap != null) {
doSomethingInAnotherThread();
}
// something can set `myMap` to null here...
计划运行的代码将在某个时候运行
void inAnotherThread() {
myMap.access();
}
但是不能保证myMap
与以前一样。如果有线程可以更改myMap
所指的内容,则执行以下操作
void inAnotherThread() {
if (myMap != null) {
myMap.acess();
}
}
仍然不是线程安全的,因为您访问myMap
两次,每次都可能不同。例如,if
中的值不为空,但一旦您访问该值,该值即为null
。一种解决方案是复制引用,以便在使用该引用时,任何内容都不能更改该引用的本地副本
void inAnotherThread() {
Map localReference = myMap;
if (localReference != null) {
localReference.acess();
}
}
这是否是线程安全取决于myMap
。例如,它是否为易变的(或是最终的)。如果是:其他线程保证看到myMap
引用的最新版本,如果不是:不保证。(注意:我认为runOnUiThread
建立了一个“发生在之前”的关系,因为它在内部同步,因此您应该有某种程度的保证可以看到引用的最新版本)
一旦您有了对正确的Map
实例的引用,下一点就是您可以安全地使用它。简单的HashMap
使用起来不是线程安全的。如果您调用.get()
它仍然可能在您身上爆炸,如果同时另一个线程调用put
/remove
/。。因此在.get
访问数据时会更改数据
您可以将它包装在集合中。synchronizedMap(map)
将使等单个操作成为原子操作,以便其他线程不会干扰。但它仍然不是每件事都是线程安全的。例如,如果不进行外部同步,迭代值仍将失败。这个问题可以通过使用同样支持迭代的ConcurrentHashMap
来解决
线程安全性取决于许多因素以及您对什么是线程安全的定义。如果你能保证,你写的已经是线程安全的了