Ваша общая структура не поточно-
Поток, который инициирует весь процесс проверки 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
. Для одного ли это volatile
(или final
) или нет. Если это так: в других потоках гарантируется самая последняя версия того, что означает myMap
, если нет: ничего не гарантировано. (Примечание: Я думаю, что runOnUiThread
создан происходит, прежде, чем отношения, поскольку она синхронизирует внутри, и поэтому вы должны иметь какое-то гарантию, чтобы увидеть последнюю версию ссылки)
Следующей точку когда у вас есть ссылка на правильный Map
экземпляр - это то, что вы можете сделать с ним безопасно. Простой HashMap
не является потокобезопасным в использовании.Если вы вызываете .get()
, он все равно может взорваться на вас, если - в то же время - другой поток вызывает put
/remove
/.. и поэтому изменяет данные, а .get
обращается к нему.
Вы можете обернуть его в Collections.synchronizedMap(map)
, который сделал бы одиночные операции, такие как get
атомарным, чтобы другие потоки не могли вмешиваться. Но это все еще не потокобезопасно для всего. Например. итерация по значениям будет по-прежнему терпеть неудачу, если вы не будете синхронизировать извне. Эту проблему можно решить, используя ConcurrentHashMap
, который поддерживает итерацию.
Threadsfety зависит от множества факторов и от определения того, что такое поточный сейф. То, что вы написали, уже является потокобезопасным, если вы можете гарантировать, что myMap
никогда не будет изменен, если он установлен на != null
, и вы знаете, что фоновый поток выполнен с модификацией myMap
, поэтому для UiThread это безопасно.
запустите этот код после инициализации myMap Map, поэтому он не будет пустым. –
Из какой темы вы это называете? Если он вызывается из UiThread, он будет выполняться непосредственно в строке, как если бы не было «Runnable». – zapl
Я забыл упомянуть, что код не запускается из потока пользовательского интерфейса. Gonna edit that in. – npace