Android线程间通信的3中方式

来源:互联网 发布:校园网络暴力案例 编辑:程序博客网 时间:2024/05/19 23:26

1. 使用管道流Pipes

“管道”是java.io包的一部分。它是Java的特性,而不是Android特有的。一条“管道”为两个线程建立一个单向的通道。生产者负责写数据,消费者负责读取数据。

下面是一个使用管道流进行通信的例子。

 

view sourceprint?
01.public class PipeExampleActivity extends Activity {
02. 
03.private static final String TAG = "PipeExampleActivity";
04.private EditText editText;
05. 
06.PipedReader r;
07.PipedWriter w;
08. 
09.private Thread workerThread;
10. 
11.public void onCreate(Bundle savedInstanceState) {
12.super.onCreate(savedInstanceState);
13. 
14.r = new PipedReader();
15.w = new PipedWriter();
16. 
17.try {
18.w.connect(r);
19.catch (IOException e) {
20.e.printStackTrace();
21.}
22. 
23.setContentView(R.layout.activity_pipe);
24.editText = (EditText) findViewById(R.id.edit_text);
25.editText.addTextChangedListener(new TextWatcher() {
26.@Override
27.public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
28.}
29. 
30.@Override
31.public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
32.try {
33.if(count > before) {
34.w.write(charSequence.subSequence(before, count).toString());
35.}
36.catch (IOException e) {
37.e.printStackTrace();
38.}
39.}
40. 
41.@Override
42.public void afterTextChanged(Editable editable) {
43.}
44.});
45. 
46.workerThread = new Thread(new TextHandlerTask(r));
47.workerThread.start();
48.}
49. 
50.@Override
51.protected void onDestroy() {
52.super.onDestroy();
53.workerThread.interrupt();
54.try {
55.r.close();
56.w.close();
57.catch (IOException e) {
58.}
59.}
60. 
61.private static class TextHandlerTask implements Runnable {
62.private final PipedReader reader;
63. 
64.public TextHandlerTask(PipedReader reader){
65.this.reader = reader;
66.}
67.@Override
68.public void run() {
69.while(!Thread.currentThread().isInterrupted()){
70.try {
71.int i;
72.while((i = reader.read()) != -1){
73.char c = (char) i;
74. 
75.Log.d(TAG, "char = " + c);
76.}
77. 
78.catch (IOException e) {
79.e.printStackTrace();
80.}
81.}
82.}
83.}
84.}

在这个例子中,对EditText设置一个TextWatcher监听,一旦EditText的内容发生改变,就向“管道”中输入字符,它就是所谓的生产者。同时,有一个工作线程负责从管道中读取字符,它就是所谓的消费者。这样,就实现了UI线程和工作线程之间的数据通信。

 

 

2. 共享内存

多个线程共享同一份内存,就是说,一个变量可以同时被多个线程所访问。这里要特别注意同步和原子操作的问题。

Java中最基本的同步例子。

 

view sourceprint?
1.synchronized(this) {
2.while(isConditionFullfilled == false) {
3.wait();
4.}
5. 
6. 
7.notify();
8.}
如果觉得使用wait/notify比较麻烦,可以使用Java提供的BlockingQueue,从名字就可以看出它是一个阻塞队列。看下面的例子。

 

 

view sourceprint?
01.public class ConsumerProducer {
02.private final int LIMIT = 10;
03.private BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<Integer>(LIMIT);
04. 
05.public void produce() throws InterruptedException {
06.int value = 0;
07.while (true) {
08.blockingQueue.put(value++);
09.}
10.}
11. 
12.public void consume() throws InterruptedException {
13.while (true) {
14.int value = blockingQueue.take();
15.}
16.}
17. 
18.}

3. 使用Hander和Message

 

Handler的机制网上有很多教程,对其不太清楚的同学可以Google一下。

我做一下简略的总结。

一个线程对应一个Looper,一个Looper持有一个MessageQueue,一个Looper可以与多个Handler绑定,一个MessageQueue中可以包含多个Message。

下面是一个使用Handler的例子。

 

view sourceprint?
01.public class HandlerExampleActivity extends Activity {
02. 
03.private final static int SHOW_PROGRESS_BAR = 1;
04.private final static int HIDE_PROGRESS_BAR = 0;
05.private BackgroundThread mBackgroundThread;
06. 
07.private TextView mText;
08.private Button mButton;
09.private ProgressBar mProgressBar;
10. 
11.@Override
12.public void onCreate(Bundle savedInstanceState) {
13.super.onCreate(savedInstanceState);
14.setContentView(R.layout.activity_handler_example);
15. 
16.mBackgroundThread = new BackgroundThread();
17.mBackgroundThread.start();
18. 
19.mText = (TextView) findViewById(R.id.text);
20.mProgressBar = (ProgressBar) findViewById(R.id.progress);
21.mButton = (Button) findViewById(R.id.button);
22.mButton.setOnClickListener(new View.OnClickListener() {
23.@Override
24.public void onClick(View v) {
25.mBackgroundThread.doWork();
26.}
27.});
28.}
29. 
30.@Override
31.protected void onDestroy() {
32.super.onDestroy();
33.mBackgroundThread.exit();
34.}
35. 
36.private final Handler mUiHandler = new Handler() {
37.public void handleMessage(Message msg) {
38. 
39.switch(msg.what) {
40.case SHOW_PROGRESS_BAR:
41.mProgressBar.setVisibility(View.VISIBLE);
42.break;
43.case HIDE_PROGRESS_BAR:
44.mText.setText(String.valueOf(msg.arg1));
45.mProgressBar.setVisibility(View.INVISIBLE);
46.break;
47.}
48.}
49.};
50. 
51.private class BackgroundThread extends Thread {
52. 
53.private Handler mBackgroundHandler;
54. 
55.public void run() {
56.Looper.prepare();
57.mBackgroundHandler = new Handler();
58.Looper.loop();
59.}
60. 
61.public void doWork() {
62.mBackgroundHandler.post(new Runnable() {
63.@Override
64.public void run() {
65.Message uiMsg = mUiHandler.obtainMessage(SHOW_PROGRESS_BAR, 0,
66.0null);
67.mUiHandler.sendMessage(uiMsg);
68. 
69.Random r = new Random();
70.int randomInt = r.nextInt(5000);
71.SystemClock.sleep(randomInt);
72. 
73.uiMsg = mUiHandler.obtainMessage(HIDE_PROGRESS_BAR, randomInt,
74.0null);
75.mUiHandler.sendMessage(uiMsg);
76.}
77.});
78.}
79. 
80.public void exit() {
81.mBackgroundHandler.getLooper().quit();
82.}
83.}
84.}
0 0