Android并发编程线程间通信的三种基本方式

来源:互联网 发布:紧急避孕药 知乎 编辑:程序博客网 时间:2024/05/04 16:37

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();        }    }}




0 0
原创粉丝点击