Java & Android 多线程
2012-10-15 14:35
295 查看
《Java & Android 多线程》
一.Java Thread 小结:
1. 我们要实现多线程,必须编写一个继承了Thread 类的子类,子类要覆盖 Thread 类中的 run 函数,在子类的 run 函数中调用想在新线程上运行的程序代码 。2. 启动一个新的线程,我们不是直接调用 Thread 的子类对象的 run 方法,而是调 用Thread 子类对象的 start (从 Thread 类中继承的)方法 , Thread 类对象的 start 方法将产生一个新的线程(注意:对于同一个Thread对象,多次使用start方法,并不会创建多个线程!),并在该线程上运行该 Thread 类对象中的 run 方法,根据面向对象的多态性,在该线程上实际运行的是 Thread 子类(也就是我们编写的那个类)对象中的 run 方法 。
3. 由于线程的代码段在 run 方法中,那么该方法执行完成以后线程也就相应的结束了 ,因而我们可以通过控制 run 方法中的循环条件来控制线程的终止。
二.用 Runnable 接口创建多线程
在 JDK 文档中,我们还看到了一个 Thread(Runnable target) 构造方法。Runnable是一个接口,不是一个线程,一般线程会实现Runnable。从 JDK 文档中查看 Runnable 接口类的帮助,该接口中只有一个 run() 方法,当我们使用 Thread(Runnable target) 方法创建线程对象时,需为该方法传递一个实现了 Runnable 接口的类对象。
这样创建的线程将调用那个实现了 Runnable 接口的类对象中的 run() 方法作为其运行代码(所以我们自己要实现Runnable的Run方法),而不再调用 Thread 类中的 run 方法了。当然,还是要对Thread对象调用start方法的。
三.实现 Runnable 接口相对于继承 Thread 类来说,有如下显著的好处:
1 、适合多个相同程序代码的线程去处理同一资源的情况,2 、 可以避免由于 Java 的单继承特性带来的局限 。 3 、有利于程序的健壮性, 代码能够被多个线程共享,代码与数据是独立的。
事实上,几乎所有多线程应用都可用第二种方式,即实现 Runnable 接口。
四.Android 中的多线程
在Android中,Thread类通常和Android的Handler类共同使用,用来更新UI界面。当然,你也可以单独使用Thread类来实现一些耗时的操作,比如:下载文件。在《解密Google Android》一书中,发现了这样一个启动线程的模型。利用该模型,我们可以把一些耗时的操作放到doStuff方法中去执行,同时在updateUIHere方法中进行更新UI界面的操作,就可以完成一个线程所需要的功能。其他的说明写在注释部分了。
Handler myHandler = new Handler() {
public void handleMessage(Message msg) {
updateUIHere();
}
}
new Thread() {
public void run() {
doStuff(); // 执行耗时操作
Message msg = myHandler.obtainMessage();
Bundle b = new Bundle();
b.putString("key", "value");
m.setData(b); // 向消息中添加数据
myHandler.sendMessage(m); // 向Handler发送消息,更新UI
}
}.start();
1.Handler
对于线程的控制,我们将介绍一个Handler类,使用该类可以对运行在不同线程中的多个任务进行排队,并使用Message和Runnable对象安排这些任务。Handler对象的四个构造方法:
Handler()
Handler(Looper looper)
Handler(Handler.Callback callback)
Handler(Looper looper, Handler.Callback callback)
第一个和第二个比较常用。下面就是常见的用法和解释:
a、如果new一个无参构造函数的Handler对象,那么这个Handler将自动与当前运行线程相关联,也就是说这个Handler将与当前运行的线程使用同一个消息队列,并且可以处理该队列中的消息。直接利用无参Handler对象post了一个runnable对象,相当于直接调用了Runnable对象的run函数,也就说没有经过start函数调用run(),那么就不会创建一个新线程,而是在原有线程内部直接调用run()方法,Runnable对象和主用户界面线程的ID是相同实例。
常见的新建线程的方法是:
Thread thread = new Thread();
thread.start();
HandlerThread thread = new HandlerThread("string");
thread.start();
b、 如果需要Handler对象去处理消息,那么就要重载Handler类的handleMessage函数。
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg)
{ // TODO : Handle the msg
// Usually we update UI here.
}
}
注意到注释部分,我们通常在handleMessage中处理更新UI界面的操作。
c、 如果new一个带Looper参数的Handler对象,那么这个Handler对象将与参数所表示的Looper相关联。注意:此时线程类应该是一个特殊类HandlerThread类——一个有Looper的Thread类(这也是HandlerThread类和Thread类的唯一区别)。
2.HandlerThread
Android线程,它与一般的Java多线程处理方式是不同的,其中重点是消息发送和计划任务,接受消息发送和计划任务的处理是目标线程,它是通过Looper机制维护消息队列。HandlerThread类结合了Looper的方法,所以,我们不必关心Looper。两个构造方法:
HandlerThread(String name) //用的最多的是这个。
HandlerThread(String name, int priority)
上面4.1 c中提到的Looper,如果要使用,必须先使用HandlerThread对象的start方法之后,才可以在Handler中传递这个Looper参数!举例如下:
HandlerThread handlerthread = new HandlerThread("MyThread");
handlerthread.start(); //先调用start,再传递handlerthread.getLooper()
private MyHandler handler = new MyHandler(handlerthread.getLooper());
3.Handler、Runnable和HandlerThread类的结合使用
使用的一般步骤:1.实现自定义的MyHandler、MyRunnable类。注意要重写MyHandler 的handleMessage 和MyRunnable 的run方法。
2.new一个MyHandler和MyRunnable类的对象。
3.调用Handler中分发消息的一些方法
post(Runnable) //常用
postAtTime(Runnable,long)
postDelayed(Runnable,long)
sendEmptyMessage(int)
sendMessage(Message) //常用
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
4.综合使用实例
public class chapter8_6_2 extends Activity {private Button btnEnd;
private TextView labelTimer;
private boolean isRunning = true;
private Handler handler;
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);
HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
handler = new Handler(thread.getLooper());
Runnable r = new Runnable() {
public void run() {
if (isRunning) {
labelTimer.setText("逝去了 " + timer + " 秒");
timer++;
handler.postDelayed(this, 1000);
}
}
};
handler.postDelayed(r, 1000);
}
}
相关文章推荐
- 【转】java&android线程池-Executor框架之ThreadPoolExcutor&ScheduledThreadPoolExecutor浅析(多线程编程之三)
- java&android线程池-Executor框架之ThreadPoolExcutor&ScheduledThreadPoolExecutor浅析(多线程编程之三)
- java&android线程池-Executor框架之ThreadPoolExcutor&ScheduledThreadPoolExecutor浅析(多线程编程之三)
- 黑马程序员 Java基础<五>---> 多线程
- <Android+Java>(二)第一个模拟器
- Java&&Android Executor详解
- android java.net.UnknownHostException: Unable to resolve host "...": No address associated 错误
- android java.net.UnknownHostException: Unable to resolve host "...": No address associated 错误
- Android开发手记(26) Java多线程的实现
- javaweb & android 对比理解图 系列 图一
- Form表单多文件上传(H5和Android && Java后台)
- Java、Android多线程、线程池
- android&java注解详解
- Java&Android调试方法
- java & Android 格式化字符串
- 黑马程序员Java培训、Android培训-Java 学习过程记录_多线程
- core java 10~12(多线程 & I/O & Network网络编程)
- Android Java Timer & TimerTask 学习
- Android Caused by: java.lang.IllegalArgumentException: column '_id' does not exist
- Java&Android 学习理解(2)