Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/225.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android runOnUiThread线程安全_Java_Android_Concurrency - Fatal编程技术网

Java Android runOnUiThread线程安全

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

我想知道我处理特定问题的方法是否是线程安全的(可能不是,这就是我问的原因)。假设我们在非UI线程上运行以下代码:

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
来解决

线程安全性取决于许多因素以及您对什么是线程安全的定义。如果你能保证,你写的已经是线程安全的了