После просмотра этого вопроса я думаю, что хочу обернуть ThreadLocal, чтобы добавить поведение сброса.
Я хочу иметь что-то похожее на ThreadLocal, с методом, который я могу вызвать из любого потока, чтобы установить все значения обратно на одно и то же значение. Пока у меня есть это:
public class ThreadLocalFlag {
private ThreadLocal<Boolean> flag;
private List<Boolean> allValues = new ArrayList<Boolean>();
public ThreadLocalFlag() {
flag = new ThreadLocal<Boolean>() {
@Override protected Boolean initialValue() {
Boolean value = false;
allValues.add(value);
return value;
}
};
}
public boolean get() {
return flag.get();
}
public void set(Boolean value) {
flag.set(value);
}
public void setAll(Boolean value) {
for (Boolean tlValue : allValues) {
tlValue = value;
}
}
}
Я обеспокоен тем, что автобокс примитива может означать, что копии, которые я сохранил в списке, не будут ссылаться на те же переменные, на которые ссылается ThreadLocal, если я попытаюсь установить их. Я еще не тестировал этот код, и с чем-то хитрым, как это, я ищу совет специалиста, прежде чем я продолжу этот путь.
Кто-то спросит: «Зачем ты это делаешь?». Я работаю в среде, где есть другие потоки, которые вызывают обратный вызов в моем коде, и у меня нет ссылок на них. Периодически я хочу обновить значение в переменной ThreadLocal, которую они используют, поэтому для выполнения этого обновления требуется, чтобы поток, использующий переменную, выполнил обновление. Мне просто нужен способ уведомить все эти потоки, что их переменная ThreadLocal устарела.
Я польщен тем, что в последнее время появилась новая критика в отношении этого трехлетнего вопроса, хотя я чувствую, что его тон немного меньше профессионального. Решение, которое я предоставил, работало без происшествий в течение этого времени. Однако должны быть лучшие способы достижения цели, которая поставила этот вопрос, и я приглашаю критиков дать ответ, который явно лучше. С этой целью я постараюсь быть более ясным в отношении проблемы, которую пытался решить.
Как я упоминал ранее, я использовал фреймворк, где несколько потоков используют мой код, вне моего контроля. Эта среда была QuickFIX / J, и я реализовывал интерфейс приложения . Этот интерфейс определяет ловушки для обработки сообщений FIX, и в моем случае инфраструктура была настроена на многопоточность, чтобы каждое соединение FIX с приложением могло обрабатываться одновременно.
Тем не менее, среда QuickFIX / J использует только один экземпляр моей реализации этого интерфейса для всех потоков. Я не контролирую, как потоки запускаются, и каждый обслуживает отдельное соединение с различными деталями конфигурации и другим состоянием. Было естественно позволить некоторым из этого состояния, к которому часто обращаются, но редко обновляют, жить в различных ThreadLocal
s, которые загружают свое начальное значение, как только среда запускает поток.
В других частях организации у нас был библиотечный код, позволяющий нам регистрироваться для обратных вызовов для уведомления о деталях конфигурации, которые изменяются во время выполнения. Я хотел зарегистрироваться для этого обратного вызова, и когда я получил его, я хотел, чтобы все потоки знали, что пришло время перезагрузить значения этих ThreadLocal
s, поскольку они, возможно, изменились. Этот обратный вызов происходит из потока, который я не контролирую, как потоки QuickFIX / J.
Мое решение, приведенное ниже, использует ThreadLocalFlag
(обернутый ThreadLocal<AtomicBoolean>
) исключительно для того, чтобы сигнализировать другим потокам, что, возможно, пришло время обновить их значения. Обратный вызов вызывает setAll(true)
, а потоки QuickFIX / J вызывают set(false)
, когда они начинают свое обновление. Я преуменьшил проблемы параллелизма ArrayList
, поскольку список добавлялся только во время запуска, и мой вариант использования был меньше размера списка по умолчанию.
Я полагаю, что ту же задачу можно выполнить с помощью других методов межпотоковой коммуникации, но для того, что она делает, это казалось более практичным. Я приветствую другие решения.