#android
#Android
Вопрос:
У меня есть метод updateFoo () действия, вызываемый как из потока обработчика каждые 5 секунд, так и с кнопки, когда пользователь хочет ее нажать … updateFoo обновляет интерфейс моего действия… чтобы сделать этот метод потокобезопасным, я объявил его «синхронизированным» … Это правильный путь???
Ответ №1:
Хорошо использовать обработчик: http://developer.android.com/reference/android/os/Handler.html является потокобезопасным. Вы можете посмотреть руководство здесь: http://mindtherobot.com/blog/159/android-guts-intro-to-loopers-and-handlers Я советую вам выполнять длительные вычисления в потоках и обновлять пользовательский интерфейс с помощью обработчика (созданного в главном потоке), вызываемого из вашего рабочего потока.
Ответ №2:
Маркировка метода synchronized
— это способ сделать его потокобезопасным — по сути, это делает так, что в методе в любой момент времени может находиться только один поток.
Однако это может быть не лучшим вариантом, потому что, updateFoo()
если вы выполняете некоторые длительные операции, ваш поток пользовательского интерфейса может зависнуть (т. Е. нажатие кнопки может застрять в ожидании входа в [и выполнения] updateFoo()
.
Более детализированным методом было бы использование блокировок или некоторых других опций потоковой обработки Java. Если вы опубликуете код для своего метода, мы сможем найти лучшее решение.
Ответ №3:
Спасибо всем за ответы 🙂 Я попробовал этот код, более простой, чем проект, который я создаю:
package provadroid.prova;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class AndroidSynch extends Activity {
private TextView text_to_view;
private Button change_text;
private static final Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.change_text = (Button)this.findViewById(R.id.change_button);
this.text_to_view = (TextView)this.findViewById(R.id.text_to_view);
this.change_text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
AndroidSynch.this.updateText(" Button ");
}
});
doTheAutoRefresh(5000);
}
synchronized void updateText(String str)
{
this.text_to_view.setText(this.text_to_view.getText() str);
}
void doTheAutoRefresh(long time) {
handler.removeMessages(0);
handler.postDelayed(new Runnable() {
@Override
public void run() {
AndroidSynch.this.updateText(" Handler ");
AndroidSynch.this.doTheAutoRefresh(5000);
}
}, time);
}
}
Фоновый обработчик запускается в фоновом режиме каждые 5 секунд, после чего обновляет textview.. Кнопка также обновляет textview…
Кажется, все работает хорошо как с функцией synchronized in update_text, так и без нее…Я полагаю, это происходит потому, что update_text работает в пользовательском интерфейсе, поэтому обработчик имеет эксклюзивный доступ и ждет, если кто-то вызывает update_text .. Но если функция не работает в пользовательском интерфейсе и вызывается обработчиком и кнопкой или другим обработчиком, я должен объявить ее синхронизированной, верно??
Ответ №4:
Если вы используете параллелизм передачи сообщений, вам не нужно слишком беспокоиться о конфликтах параллелизма. Чтобы сделать это, вы должны передать неизменяемый объект для запуска потока, поток не будет читать или записывать в какую-либо общую память за пределами потока, и поток затем вернет неизменяемый объект.
Если вы используете обмен данными с общей памятью, ИМХО, простого объявления вашего метода synchronized может быть или не быть достаточно для обеспечения потокобезопасности. Если метод, В свою очередь, обращается к общей памяти, которая не является потокобезопасной, атомарной и т.д., Могут возникнуть конфликты параллелизма.