1. 程式人生 > >【Android 併發程式設計】執行緒間通訊的三種基本方式,android執行緒

【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();
}
如果覺得使用wait/notify比較麻煩,可以使用Java提供的BlockingQueue,從名字就可以看出它是一個阻塞佇列。看下面的例子。
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,另一個子執行緒發訊息,收到訊息的就是子執行緒而不是主執行緒了。