一、android线程的定义和特点
1、什么是线程:
线程是一种轻量级进程,大多数情况下用于执行异步操作。在一个android程序开始运行的时候,会单独启动一个进程,同时会产生一个UIThread线程(主线程)。一个android程序默认情况下只有一个进程,但是一个进程下可以有多个线程。
2、线程与进程的区别:
(1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
(2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
(3)线程是处理器调度的基本单位,但进程不是
(4)线程只需要很少的资源就可“轻装上阵”运行的优点,来弥补进程并发的“颗粒度”粗糙的缺点,提高系统资源(如:CPU,内存——又可分为数据区,堆栈区等等,和IO总线控制权……)利用率。
二、为什么要用线程?
1、用于异步操作
2、默认的情况下,Service和Activity(还有Content Provider和Broadcast Receiver)会同时运行在进程的main线程中,是会相互阻塞的。因此要在服务中执行长时间的操作(如网络应用)时,还是要自己创建线程来操作。
三、线程的实现方法
1、继承java.lang.Thread类,重载它的run()方法和start()函数来启动线程:
Thread thread=new Thread(new Runnable(){
@Override
public void run() {
Message message = new Message();
message.what=1;
mHandler.sendMessage(message);
}
)};
thread.start();
2、实现Runnalbe接口,重载它的run()方法,用start()函数来启动线程:
public class Runnalble_Demo extends Activity implements Runnable {
public Button button;
public LinearLayout my_layout;
public Handler mHandler=new Handler() {
public void handleMessage(Message msg){
switch(msg.what) {
case 1:
button.setText(R.string.text2);
break;
default:
break;
}
my_layout.invalidate();
super.handleMessage(msg);
}; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
my_layout=(LinearLayout)findViewById(R.id.my_layout);
Thread thread=new Thread(this);
}
@Override
public void run() {
Message message = new Message();
message.what=1;
mHandler.sendMessage(message);
}
}
三、既然说的是Android,我们不得不提到的是AsyncTask
AsyncTask是Android框架提供的异步处理的辅助类,它可以实现耗时操作在其他线程执行,而处理结果在Main线程执行。使用他你会发现你的代码很容易被理解,因为他们都有一些具有特定职责的方法,尤其是AsyncTask,有预处理的方法onPreExecute,有后台执行任务的方法doInBackground,有更新进度的方法publishProgress,有返回结果的方法onPostExecute等等。不过封装越好越高级的API,对初级程序员反而越不利,就是你不了解它的原理。当你需要面对更加复杂的情况,而高级API无法完成得很好时,你就杯具了
public void onClick(View v){
new DownloadImageTask().execute("http://gkimg.cdn.midasjoy.com/Uploads/picture/20171026/59f17bbeb0218.png");
}
private class DownloadImageTask extends AsyncTask{
protected Bitmap doInBackground(String ... urls){
return loadImageFromNetWork(urls[0]);//加载网络图片的方法,此处略
}
protected void onPostExecute(Bitmap result){
mImageView.setImageBItmap(result);
}
}
四、那么,继承Thread类与实现Runnable接口有什么区别?优缺点?
1、Thread 类实现了Runnable接口
2、在Java中,类仅支持单继承,也就是说,当定义一个新的类的时候,它只能扩展一个外部类.
如果自定义线程类继承自Thread,那么它无法再继承其他类,拥有其他类的方法,降低了类的扩展性。但是,如果通过实现Runnable接口,你就可以继承其他类了。
3、还有一点最重要,就是使用实现Runnable接口的方式创建的线程可以处理同一资源,从而实现资源的共享:
比如模拟一个火车站的售票系统,假如只有100张火车篇,且允许所有窗口卖这100张票,那么每一个窗口也相当于一个线程,但需要处理的资源是同一个资源,即100张车票。如果还用前面的方式来创建线程显然是无法实现的,这种情况该怎样处理呢?看下面这个程序:
public class MutliThreadDemo {
public static void main(String[] args) {
MutliThread m=new MutliThread();
Thread t1=new Thread(m);
Thread t2=new Thread(m);
Thread t3=new Thread(m);
t1.start();
t2.start();
t3.start();
}
public class MutliThread implements Runnable{
private int ticket=100;//每个线程都拥有100张票
public void run(){
while(ticket>0){
System.out.println(ticket--+" is saled by "+Thread.currentThread());
}
}
}
程序在内存中仅创建了一个资源,而新建的三个线程都是基于访问这同一资源的,并且由于每个线程上所运行的是相同的代码,因此它们执行的功能也是相同的。可见,如果现实问题中要求必须创建多个线程来执行同一任务,而且这多个线程之间还将共享同一个资源,那么就可以使用实现Runnable接口的方式来创建多线程程序。这样一来,线程、代码和数据资源三者有效分离,很好地体现了面向对象程序设计的思想。因此,几乎所有的多线程程序都是通过实现Runnable接口的方式来完成的。