管道流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线程和工作线程之间的数据通信。
共享内存
多个线程共享同一份内存。就是说,一个变量可以同时被多个线程所访问。这里要特别注意同步和原子操作的问题。
synchronized(this) {
while(isConditionFullfilled == false) {
wait();
}
notify();
}
如果觉得使用wait/notify不容易控制,可以使用Java提供的BlockingQueue,它是一个阻塞队列。
public class ConsumerProducer {
private final int LIMIT = 10;
private BlockingQueue blockingQueue = new LinkedBlockingQueue(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();
}
}
}
使用Hander和Message
一个线程对应一个Looper,一个Looper持有一个MessageQueue,一个Looper可以与多个Handler绑定,一个MessageQueue中可以包含多个Message。
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();
}
}
}
参考资料
http://developer.android.com/reference/java/io/PipedInputStream.html
http://developer.android.com/reference/java/io/PipedOutputStream.html
https://engineering.purdue.edu/~smidkiff/ece563/files/java.pdf
http://developer.android.com/reference/android/os/Handler.html