【Android 併發程式設計】執行緒間通訊的三種基本方式,android執行緒
1. 使用管道流Pipes
“管道”是java.io包的一部分。它是Java的特性,而不是Android特有的。一條“管道”為兩個執行緒建立一個單向的通道。生產者負責寫資料,消費者負責讀取資料。
下面是一個使用管道流進行通訊的例子。
public class PipeExampleActivity extends Activity { private static final String TAG = "PipeExampleActivity"; private EditText editText; PipedReader r; PipedWriter w; private Thread workerThread; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); r = new PipedReader(); w = new PipedWriter(); try { w.connect(r); } catch (IOException e) { e.printStackTrace(); } setContentView(R.layout.activity_pipe); editText = (EditText) findViewById(R.id.edit_text); editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) { } @Override public void onTextChanged(CharSequence charSequence, int start, int before, int count) { try { if(count > before) { w.write(charSequence.subSequence(before, count).toString()); } } catch (IOException e) { e.printStackTrace(); } } @Override public void afterTextChanged(Editable editable) { } }); workerThread = new Thread(new TextHandlerTask(r)); workerThread.start(); } @Override protected void onDestroy() { super.onDestroy(); workerThread.interrupt(); try { r.close(); w.close(); } catch (IOException e) { } } private static class TextHandlerTask implements Runnable { private final PipedReader reader; public TextHandlerTask(PipedReader reader){ this.reader = reader; } @Override public void run() { while(!Thread.currentThread().isInterrupted()){ try { int i; while((i = reader.read()) != -1){ char c = (char) i; Log.d(TAG, "char = " + c); } } catch (IOException e) { e.printStackTrace(); } } } } }
在這個例子中,對EditText設定一個TextWatcher監聽,一旦EditText的內容發生改變,就向“管道”中輸入字元,它就是所謂的生產者。同時,有一個工作執行緒負責從管道中讀取字元,它就是所謂的消費者。這樣,就實現了UI執行緒和工作執行緒之間的資料通訊。
2. 共享記憶體
多個執行緒共享同一份記憶體,就是說,一個變數可以同時被多個執行緒所訪問。這裡要特別注意同步和原子操作的問題。
Java中最基本的同步例子。
synchronized(this) { while(isConditionFullfilled == false) { wait(); } notify(); }
public class ConsumerProducer { private final int LIMIT = 10; private BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<Integer>(LIMIT); public void produce() throws InterruptedException { int value = 0; while (true) { blockingQueue.put(value++); } } public void consume() throws InterruptedException { while (true) { int value = blockingQueue.take(); } } }
3. 使用Hander和Message
Handler的機制網上有很多教程,對其不太清楚的同學可以Google一下。
我做一下簡略的總結。
一個執行緒對應一個Looper,一個Looper持有一個MessageQueue,一個Looper可以與多個Handler繫結,一個MessageQueue中可以包含多個Message。
下面是一個使用Handler的例子。
public class HandlerExampleActivity extends Activity { private final static int SHOW_PROGRESS_BAR = 1; private final static int HIDE_PROGRESS_BAR = 0; private BackgroundThread mBackgroundThread; private TextView mText; private Button mButton; private ProgressBar mProgressBar; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_handler_example); mBackgroundThread = new BackgroundThread(); mBackgroundThread.start(); mText = (TextView) findViewById(R.id.text); mProgressBar = (ProgressBar) findViewById(R.id.progress); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mBackgroundThread.doWork(); } }); } @Override protected void onDestroy() { super.onDestroy(); mBackgroundThread.exit(); } private final Handler mUiHandler = new Handler() { public void handleMessage(Message msg) { switch(msg.what) { case SHOW_PROGRESS_BAR: mProgressBar.setVisibility(View.VISIBLE); break; case HIDE_PROGRESS_BAR: mText.setText(String.valueOf(msg.arg1)); mProgressBar.setVisibility(View.INVISIBLE); break; } } }; private class BackgroundThread extends Thread { private Handler mBackgroundHandler; public void run() { Looper.prepare(); mBackgroundHandler = new Handler(); Looper.loop(); } public void doWork() { mBackgroundHandler.post(new Runnable() { @Override public void run() { Message uiMsg = mUiHandler.obtainMessage(SHOW_PROGRESS_BAR, 0, 0, null); mUiHandler.sendMessage(uiMsg); Random r = new Random(); int randomInt = r.nextInt(5000); SystemClock.sleep(randomInt); uiMsg = mUiHandler.obtainMessage(HIDE_PROGRESS_BAR, randomInt, 0, null); mUiHandler.sendMessage(uiMsg); } }); } public void exit() { mBackgroundHandler.getLooper().quit(); } } }
救命 android執行緒間通訊 handler message之類的
執行緒間通訊(三種方式)::
public class AnrActivity extends Activity implements OnClickListener {
TextView text;
Handler handler;
ProgressBar bar;
private class MyAsycnTask extends AsyncTask<URL, Integer, String>{
@Override
protected void onProgressUpdate(Integer... values) {
bar.setProgress(values[0]);
text.setText("進度:"+values[0]+"%");
super.onProgressUpdate(values);
}
@Override
protected String doInBackground(URL... params) {
for (int i = 0; i <100; i++) {
try {
publishProgress(i+1);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "success";
}
@Override
protected void onPostExecute(String result) {
text.setText(result);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button down = (Button) this.findViewById(R.id.button1);
Button receiver = (Button) this.findViewById(R.id.button2);
Button update = (Button)this.findViewById(R.id.button3);
bar = (ProgressBar)this.findViewById(R.id.progressBar1);
text = (TextView)this.findViewById(R.id.text);
update.setOnClickListener(this);
down.setOnClickListener(this);
receiver.setOnClickListener(this);
}
@Override
public void onClick(final View v) {
switch (v.getId()) {
case R.id.button1:
//通過 Asycntask 進行通訊
MyAsycnTask myAsycnTask = new MyAsycnTask();
myAsycnT......餘下全文>>
面試被問到android中兩個子執行緒怎通訊,我懵了
構造HandlerThread類的物件mHandlerThread,這樣生成一個子執行緒可以呼叫new MyHandler(mHandlerThread.getLooper())來獲取子執行緒的handler,另一個子執行緒發訊息,收到訊息的就是子執行緒而不是主執行緒了。