首先來看下ConditionVariable類的定義:
C:\Program Files\Android\android-sdk\platforms\android-21\android.jar
package android.os;
public class ConditionVariable
{
private volatile boolean mCondition;
/**
* Create the ConditionVariable in the default closed state.
*/
public ConditionVariable()
{
mCondition = false;
}
/**
* Create the ConditionVariable with the given state.
* Pass true for opened and false for closed.
*/
public ConditionVariable(boolean state)
{
mCondition = state;
}
/**
* Open the condition, and release all threads that are blocked.
* Any threads that later approach block() will not block unless close()
* is called.
*/
public void open()
{
synchronized (this) {
boolean old = mCondition;
mCondition = true;
if (!old) {
this.notifyAll();
}
}
}
/**
* Reset the condition to the closed state.
* Any threads that call block() will block until someone calls open.
*/
public void close()
{
synchronized (this) {
mCondition = false;
}
}
/**
* Block the current thread until the condition is opened.
* If the condition is already opened, return immediately.
*/
public void block()
{
synchronized (this) {
while (!mCondition) {
try {
this.wait();
}
catch (InterruptedException e) {
}
}
}
}
/**
* Block the current thread until the condition is opened or until
* timeout milliseconds have passed.
* @param timeout the minimum time to wait in milliseconds.
*
* @return true if the condition was opened, false if the call returns
* because of the timeout.
*/
public boolean block(long timeout)
{
// Object.wait(0) means wait forever, to mimic this, we just
// call the other block() method in that case. It simplifies
// this code for the common case.
if (timeout != 0) {
synchronized (this) {
long now = System.currentTimeMillis();
long end = now + timeout;
while (!mCondition && now < end) {
try {
this.wait(end-now);
}
catch (InterruptedException e) {
}
now = System.currentTimeMillis();
}
return mCondition;
}
} else {
this.block();
return true;
}
}
}
這裏詳述了ConditionVariable類的實現過程及其內部函數。該類內部定義了一個volatile 類型的 mCondition 變量,通過控制這個變量的值,來實現對wait()函數的調用,達到控制線程是否阻塞的目的。
這裏寫了一個簡單的實例來模擬整個控制過程
public class MainActivity extends Activity implements OnClickListener {
private Button btn_output;
private TextView textView;
private MyHandler mHandler;
private boolean isStart;
private String str = "";
private ConditionVariable mConditionVariable;
private final int REFRESHTEXT = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_output = (Button) findViewById(R.id.btn);
btn_output.setOnClickListener(this);
textView = (TextView) findViewById(R.id.txt);
mHandler = new MyHandler();
mConditionVariable = new ConditionVariable();
isStart = true;
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while(isStart) {
//延時等待3秒
mConditionVariable.block(3000);
//如果是點擊了按鈕,則先將條件重置,否則block會失效
mConditionVariable.close();
//線程喚醒後通知主線程更新TextView的文本
mHandler.sendEmptyMessage(REFRESHTEXT);
}
}
}).start();
}
private class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case REFRESHTEXT:
textView.setTextSize(20.0f);
textView.setText(str += 's');
break;
}
}
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
mConditionVariable.open();
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
isStart = false;
}
}
運行該實例,你會發現按鈕旁邊的字符串會由hello world變爲S,並且S會一直增加,每隔3秒增加一個S;
如果你有手動點擊按鈕的話,就會直接增加一個S,而不用等待3秒;
這個案例是從別處借鑑過來的,思路不錯,就實驗了一把,並且效果也不錯。
但這個代碼有一處不嚴謹的地方就是在退出該Activity時,並未將mConditionVariable對象重置,建議在onDestroy()函數中增加mConditionVariable.close()調用會顯得更爲嚴謹。