java多线程简单计时器,计时器---------------多线程案例

public class chapter8_3 extends Activity {

private

String TAG =

"

chapter8_3

";

private Button btnEnd;

private TextView labelTimer;

private Thread clockThread;

private

boolean isRunning =

true;

private

int

timer =

0;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

btnEnd = (Button) findViewById(R.id.btnEnd);

btnEnd.setOnClickListener(

new OnClickListener() {

@Override

public void onClick(View v) {

isRunning =

false;

}

});

labelTimer = (TextView) findViewById(R.id.labelTimer);

/* 线程体是Clock对象本身,线程名字为

"

Clock

" */

clockThread =

new Thread(

new Runnable() {

@Override

public void run() {

while (isRunning) {

try {

Thread.currentThread().sleep(

1000);

timer++;

labelTimer.setText(

"

逝去了

" +

timer +

"

");

Log.d(TAG,

"

lost  time

" +

timer);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

clockThread.start(); /* 启动线程 */

}

}

程序打包运行结果出现了异常,如图8-8所示。

ade48e07ff5d7b5e2550d79c620b7281.png

▲图8-8 运行结果异常图

我们打开LogCat窗口,出错日志信息如图8-9所示。

d61997c19dee5910fea4f0e04b83aab4.png

▲图8-9 出错日志

系统抛出的异常信息是“Only the original thread that created a view hierarchy can touch its views”,在Android中更新UI处理必须由创建它的线程更新,而不能在其他线程中更新。上面的错误原因就在于此。

现在分析一下上面的案例,在上面的程序中有两个线程:一个主线程和一个子线程,它们的职责如图8-10所示。

由于labelTimer是一个UI控件,它是在主线程中创建的,但是它却在子线程中被更新了,更新操作在clockThread线程的run()方法中实现,代码如下:

e2b1e6d88ca3e58c68a1421f5ab591fa.png

▲图8-10 线程职责

/* 线程体是Clock对象本身,线程名字为

"

Clock

" */

clockThread =

new Thread(

new Runnable() {

@Override

public void run() {

while (isRunning) {

try {

Thread.currentThread().sleep(

1000);

timer++;

labelTimer.setText(

"

逝去了

" +

timer +

"

");

Log.d(TAG,

"

lost  time

" +

timer);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

这样的处理违背了Android多线程编程规则,系统会抛出异常“Only the original thread that created a view hierarchy can touch its views”。

要解决这个问题,就要明确主线程和子线程的职责。主线程的职责是创建、显示和更新UI控件、处理UI事件、启动子线程、停止子线程;子线程的职责是计算逝去的时间和向主线程发出更新UI消息,而不是直接更新UI。它们的职责如图8-11所示。

79adc303f4d6c86cb66871606dd80967.png

▲图8-11 线程职责

主线程的职责是显示UI控件、处理UI事件、启动子线程、停止子线程和更新UI,子线程的职责是计算逝去的时间和向主线程发出更新UI消息。但是新的问题又出现了:子线程和主线程如何发送消息、如何通信呢?

在Android中,线程有两个对象—消息(Message)和消息队列(MessageQueue)可以实现线程间的通信。下面再看看修改之后的代码清单8-5,完整代码请参考chapter8_4工程中chapter8_4代码部分。

【代码清单8-5】

public class chapter8_4 extends Activity {

private

String TAG =

"

chapter8_3

";

private Button btnEnd;

private TextView labelTimer;

private Thread clockThread;

private

boolean isRunning =

true;

private Handler handler;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

btnEnd = (Button) findViewById(R.id.btnEnd);

btnEnd.setOnClickListener(

new OnClickListener() {

@Override

public void onClick(View v) {

isRunning =

false;

}

});

handler =

new Handler() {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case

0:

labelTimer.setText(

"

逝去了

" + msg.obj +

"

");

}

}

};

labelTimer = (TextView) findViewById(R.id.labelTimer);

/* 线程体是Clock对象本身,线程名字为

"

Clock

" */

clockThread =

new Thread(

new Runnable() {

@Override

public void run() {

int

timer =

0;

while (isRunning) {

try {

Thread.currentThread().sleep(

1000);

timer++;

/* labelTimer.setText(

"

逝去了

" +

timer +

"

"); */

Message msg =

new Message();

msg.obj =

timer;

msg.what =

0;

handler.sendMessage(msg);

Log.d(TAG,

"

lost  time

" +

timer);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

clockThread.start(); /* 启动线程 */

}

有的时候为了将Android代码变得更加紧凑,把线程的创建和启动编写在一条语句中,如下面chapter8_5的代码片段。代码清单8-6所示,完整代码请参考chapter8_5工程中 chapter8_5代码部分。

【代码清单8-6】

new Thread() {

@Override

public void run() {

int

timer =

0;

while (isRunning) {

ry {

Thread.currentThread().sleep(

1000);

timer++;

/ labelTimer.setText(

"

逝去了

" +

timer +

"

");

Message msg =

new Message();

msg.obj =

timer;

msg.what =

0;

handler.sendMessage(msg);

Log.d(TAG,

"

lost  time

" +

timer);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值