Это отличный вопрос, и у Software Monkey есть правильный ответ. Если вы хотите выполнить эффективную многопоточность, вы должны полностью понимать Java Память Модель (JMM). Обратите внимание, что модель памяти Java изменилась с JSR-133, поэтому многие старые примеры потоков, которые вы найдете, будут просто ошибочными. Например, ключевое слово volatile изменилось с почти бесполезного на теперь почти такое же принудительное, как синхронизированное ключевое слово.
Кроме того, теперь у нас есть настоящие, вездесущие многоядерные процессоры, что означает настоящую многопоточность. Многопоточность до тех пор, пока несколько лет назад имитировали его только на одноядерных процессорах, вот почему так много плохого примера кода. Раньше работал. Теперь не будет.
Серьезно, если Джошуа Блох может ошибиться, действуй очень осторожно. Это сложные вещи (и да, его код неправильный. Сделайте эту переменную изменчивой, и она будет работать во всех случаях).
Ах да, Адамски правильно понял. Используйте SwingWorker
, чтобы убедиться, что долгосрочный код выполняется в фоновом потоке, и что, когда он выполняет манипулирование данными, он должен обращаться к Swing по методу done()
. Если вам нужно прочитать, сделайте это до того, как сделает ваш SwingWorker
, и введите информацию final
.
Пример кода, который будет вызываться в EDT, скорее всего, в ActionListener или в некотором таком (psuedocode):
public void someOverlySimpleExampleThatIsCalledOnEDT() {
/*
* Any code run here is guaranteed to happen-before
* the start of a background thread.
*/
final String text = myTextField().getText();
SwingWorker sw = new SwingWorker() {
private volatile List data;
public Object doInBackground() {
//happens in background thread. No Swing access
data = myDao.getDataFromInternet(text);
return null;
}
public void done() {
//Happens in EDT. Swing away Merrill
loadDataIntoJTable(data);
}
}
sw.execute();
/*
* Any code run here happens concurrently with doInBackground(). Be careful.
* Usually leave empty
*/
}