二.Android多线程编程
1.线程的相关概念
1)相关概念:
- 程序:为了完成特定任务,用某种语言编写的一组指令集合(一组静态代码)
- 进程:运行中的程序,系统调度与资源分配的一个独立单位,操作系统会 为每个进程分配一段内存空间!程序的依次动态执行,经历代码的加载,执行, 执行完毕的完整过程!
- 线程:比进程更小的执行单元,每个进程可能有多条线程,线程需要放在一个 进程中才能执行,线程由程序负责管理,而进程则由系统进行调度!
- 多线程的理解:并行执行多个条指令,将CPU时间片按照调度算法分配给各个 线程,实际上是分时执行的,只是这个切换的时间很短,用户感觉到"同时"而已!
Android多线程编程其实并不比Java多线程编程特殊,基本都是使用相同的语法。
操作分两步:
1.先定义线程
定义一个线程只需要新建一个类继承自Thread,然后重写父类的run()方法,并在里面编写耗时逻辑即可,如下所示:
class MyThread extends Thread {
@Override
public void run() {
//处理具体的逻辑
}
}
2.启动线程
启用线程的方法 new MyThread().start();
当然,使用继承的方式耦合性有点高,更多的时候都会选择使用实现Runnable接口的方式来定义一个线程,如下所示:
class MyThread implements Runnable {
@0verride
public void run() {
//处理具体的逻辑
}
}
如果使用了这种写法,启动线程的方法也需要进行相应的改变,如下所示:
MyThread myThread = new MyThread();
new Thread(myThread).start();
有时,在进行android编程时,Android的UI也是线程不安全的。如果想要更新应用程序里的UI元素,则必须在主线程中进行,否则就会出现异常。
Demo测试1:
public class MyThread extends Thread{
@Override
public void run() {
Log.d("Tag",Thread.currentThread().getName()+".run");
}
}
MainActivity中的关键代码:
public void testThread(){
MyThread mt1=new MyThread();
MyThread mt2=new MyThread();
mt1.start();
mt2.start();
}
调用方法体:
public void btnOnClick(View view) {
testThread();
// testSale();
}
Demo测试2:
import android.util.Log;
public class MyRunnable implements Runnable{
@Override
public void run() {
Log.d("Tag",Thread.currentThread().getName()+".run");
}
}
public void testRunnable(){
MyRunnable mr1=new MyRunnable();
MyRunnable mr2=new MyRunnable();
//多个Thread对象可以共用同一个mr;
Thread t1=new Thread(mr1);
Thread t2=new Thread(mr1);
t1.start();
t2.start();
}
经典用例3:买火车票
public class SaleTicket implements Runnable{
private int ticket=20;
@Override
public void run() {
while(true){
synchronized (this){
if(ticket>0){
Log.d("Tag",Thread.currentThread().getName()+"卖出了第"+(20-ticket+1)+"张票");
ticket--;
}else{
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public void testSale(){
SaleTicket saleTicket=new SaleTicket();
Thread thread1=new Thread(saleTicket,"A代理");
Thread thread2=new Thread(saleTicket,"B代理");
Thread thread3=new Thread(saleTicket,"B代理");
Thread thread4=new Thread(saleTicket,"B代理");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
小结:
1,一个类只能燃承-一个父类,存在局限: -一个类可以实现多个接口
2,在实现Runable接口的时候调用Thread(Runnable target)创建进程时.使用同一个Runnable实例,则建立的多钱程的实例交量也是共享的。但是通过继承Thread类是不能用一一个实例建立多个线程,故而实现.使用同一个Runnable实例,则建立的多钱程的实例交量也是共享的。但是通过继承Thread类是不能用一一个实例建立多个线程,故而实现Runnable接口适合于资源共享。当然,继承Thread类也能够共享交量。能共享Thread类的static变量;3,Runnable接口Thread之间的联系:Thread类也是Runnable接口的子类;
Andorid中常用的实现方式:
new Thread(new Runnable() {
@Override
public void run() {
}
}).start();
new Thread的弊端:
a.每次new Thread新建对象性能差,
b.线程缺乏统-一管理。可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导玫死机或oom(内存泄露)。
C.缺乏更多功能.如定时执行、定期执行、线程中断。
Java单线程池的好处:
a.重用存在的线程,减少对对象的创建、消亡的开销,性能住。
b.可有效控制最大并发线程数,提高系统资源的使用率,避兔过多资
源竞争,避免堵塞,
C.提供定时执行、定期执行、单线程、并发数控制等功能。
nenCachedThreaDool
newCachedThreadPool创建一个可嫒存线程池 ,如果线程池长度超过处
理需要,可灵活回收空闲线程,若无可回收,则新建线程。