package com.example.threaddemo;
import org.apache.http.impl.client.TunnelRefusedException;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
private Button start,stop,pause;
private TextView time;
private static boolean flag=false;
private int m,s,ms;
private String show=null;
private int i=0;
private String TAG= "ThreadDemo";
private TimeThread timeThread;
private int state =1;
/**
* 在非UI线程中不能处理UI
* 借助Handler机制来更新时间的变化
*
* 1.子线程借助主线程中的handler,调用handler.sendMessage(msg)方法向主线程发送消息
* 2.这消息会被主线程放到消息队列里面
* 3.主线程的looper发现消息队列里面有消息,会调用消息处理者的handleMessage方法处理消息
* 4.在handleMessage方法中处理UI
*/
private Handler handler =new Handler()
{
public void handleMessage(android.os.Message msg)
{
if(msg.what==1)
{
time.setText(show);
}
else if(msg.what==2)
{
time.setText("00:00:00");
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
m=0;
s=0;
ms=0;
initView();
/**
* 这样实际上还是运行在主线程中
* 因为初始化的时候是获取的主线程的looper
* Handler handler2 =new Handler();相当于
* Handler handler2 =new Handler(getMainLooper());
* 所以这种情况下还是可以更新UI的
*/
Handler handler2 =new Handler(getMainLooper());
handler2.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
time.setText("当前线程:"+Thread.currentThread().getName());
//这里打印的是main 主线程
}
});
}
private void initView()
{
start = (Button) findViewById(R.id.start);
stop = (Button) findViewById(R.id.stop);
pause = (Button) findViewById(R.id.pause);
time = (TextView) findViewById(R.id.time);
start.setOnClickListener(this);
stop.setOnClickListener(this);
stop.setClickable(false);
pause.setOnClickListener(this);
pause.setClickable(false);
}
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
int id = v.getId();
switch(id)
{
case R.id.start:
flag=true;
timeThread=new TimeThread(""+(i++));
timeThread.start();
state=3;
start.setClickable(false);
pause.setClickable(true);
stop.setClickable(true);
break;
case R.id.stop:
flag=false;
m=s=ms=0;
state=1;
Message msg =new Message();
msg.what=2;
handler.sendMessage(msg);
start.setClickable(true);
pause.setClickable(false);
stop.setClickable(true);
break;
case R.id.pause:
flag=false;
state=2;
start.setClickable(true);
pause.setClickable(true);
stop.setClickable(true);
break;
}
}
/**
* 扩展java.lang.Thread类
* 在onClick中调用TimeThread的start方法,线程也就启动了,这样,整个应用就在多线程下运行。
* 注意:start()方法的调用后并不是立即执行多线程代码,而是使得该线
* 程变为可运行态(Runnable),什么时候运行是由操作系统决定的。
* 多线程程序是乱序执行。因此,只有乱序执行的代码才有必要设计为多线程。
* Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,
* 以留出一定时间给其他线程执行的机会。实际上所有的多线程代码执行顺序都是不确定的,每次执行的结果都是随机的。
* @author tang
*
*/
class TimeThread extends Thread
{
public TimeThread(String name)
{
super(name);
}
@Override
public void run()
{
Log.i(TAG, getName());
// TODO Auto-generated method stub
try {
while(flag)
{
Thread.sleep(10);
ms+=1;
if(ms == 100)
{
ms=0;
s+=1;
if(s==60)
{
s=0;
m+=1;
}
}
Message msg =new Message();
msg.what=1;
handler.sendMessage(msg);
show = m+":"+s+":"+ms;
}
if(!flag)
{
if(state ==1)
{
Message msg =new Message();
msg.what=2;
handler.sendMessage(msg);
}
}
i=0;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 通过实现Runnable接口,使得该类有了多线程类的特征。
* run()方法是多线程程序的一个约定。所有的多线程代码都在run方法里面。Thread类实际上也是实现了Runnable接口的类。
* 在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target)
* 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。
* 实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。
* 因此,不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的
*/
// class TimeRunnable implements Runnable
// {
// @Override
// public void run() {
// // TODO Auto-generated method stub
// // do something you need
// }
// }
// TimeRunnable runnable =new TimeRunnable();
// Thread thread =new Thread(runnable);
// thread.start();
//
// 其实android更习惯于这样写:
// new Thread(new Runnable() {
// @Override
// public void run() {
// // TODO Auto-generated method stub
// // do something you need
// }
// }).start();
//Thread类一些API
// void setPriority(int newPriority)
// 更改线程的优先级。
// void interrupt()
// 中断线程。
// static boolean interrupted()
// 测试当前线程是否已经中断。
// boolean isAlive()
// 测试线程是否处于活动状态。
// boolean isDaemon()
// 测试该线程是否为守护线程。
// boolean isInterrupted()
// 测试线程是否已经中断。
// void join()
// 等待该线程终止。
// void join(long millis)
// 等待该线程终止的时间最长为 millis 毫秒。
// void join(long millis, int nanos)
// 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。
// long getId()
// 返回该线程的标识符。
// String getName()
// 返回该线程的名称。
// int getPriority()
// 返回线程的优先级。
// Thread.State getState()
// 返回该线程的状态。
// static void sleep(long millis)
// 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
// static void sleep(long millis, int nanos)
// 在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行)。
// void start()
// 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
// void stop()
// void stop(Throwable obj)
// 已过时。 该方法具有固有的不安全性。
// 用 Thread.stop 来终止线程将释放它已经锁定的所有监视器
// (作为沿堆栈向上传播的未检查 ThreadDeath 异常的一个自然后果)。
// 如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,
// 这有可能导致任意的行为。
// void suspend()
// 已过时。 该方法已经遭到反对,因为它具有固有的死锁倾向。
// 如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,
// 则在目标线程重新开始以前任何线程都不能访问 该资源。
// 如果重新开始目标线程的线程想在调用 resume 之前锁定该监视器,则会发生死锁。
}
多线程学习
最新推荐文章于 2022-08-15 15:43:47 发布