Android开发秘籍学习笔记(二)

  Android中有关线程Thread等相关知识的笔记

线程Thread
  每个应用程序在创建时都会默认运行单一的进程,其中包含所有的任务。为避免用户界面被挂起,那些耗时的任务 ,诸如网络下载或密集的计算,应当驻留于单独的后台线程中,如何适当地实现这种操作由开发者决定,但之后则是由Android系统基于开发者的实现来确定线程的优先级。
  大多数应用程序都通过使用线程来提升性能。如果用户界面的挂起在软件设计阶段没有被发觉,到了测试阶段就会迅速体现出来,因为Android系统会在用户界面挂起时弹出警告—告诉用户Slow app isn’t responding.

Android Thread的使用方法:
  Thread的使用方法主要有两种方法:其中一种是extends Thread,然后重载Thread的run()函数,另一种是构建一个新的Thread对象,可带Runnable或不带。但不管怎么样,都是要通过start()函数来运行相应的代码
构建Thread对象的方法如下:
1、Thread()不代任何参数,该方法会在构建的时候自动生成线程名字。
举例:

     Thread mThread = new Thread(){
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("This is thread_test");
                super.run();
            }
        };
        mThread.start();
        System.out.println(mThread.getName());

得到的logcat:

04-27 09:22:08.692: INFO/System.out(831): Thread-10
04-27 09:22:08.702: INFO/System.out(831): This is thread_test

2、Thread(Runnable runnable)该函数多了Runnable个对象,被运行的代码在Runnable对象里。
举例:

      Runnable mRunnable = new Runnable(){
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("This is thread with Runnable");
            }

        };
        Thread mThread = new Thread(mRunnable);
        mThread.start();
        System.out.println(mThread.getName());

得到的logcat:

04-27 09:37:47.832: INFO/System.out(865): Thread-11
04-27 09:37:47.861: INFO/System.out(865): This is thread with Runnable

3、Thread(Runnable runnable,String threadName)该函数有Runnable也有自己的名字threadName。
举例:

     Runnable mRunnable = new Runnable(){
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("This is thread with Runnable and Name");
            }

        };
        Thread mThread = new Thread(mRunnable,"mThreadTest");
        mThread.start();
        System.out.println(mThread.getName());

得到的logcat:

04-27 09:44:03.682: INFO/System.out(900): mThreadTest
04-27 09:44:03.702: INFO/System.out(900): This is thread with Runnable and Name

Runable和Thread的关系
  在java中可有两种方法实现多线程,一种是继承Thread类,一种是实现Runnable接口;
1)继承Thread类的方式

Thread类是在java.lang包中定义的 。一个类只要继承了Thread类同时覆写了本类中的run()
步骤就可以实现多线程操作了,然而一个类只能继承一个父类,这是此种方法的的局限 。 下面看例子:

class MyThread extends Thread{
    private String name;
    public MyThread(String name) {
    super();
    this.name = name;
    }
    public void run() {
    for(int i=0;i<10;i++) {
    System.out.println("线程开端:"+this.name+",i="+i);
    }
    }
}
public class ThreadDemo01 {
    public static void main(String[] args) {
        MyThread mt1=new MyThread("线程a");
        MyThread mt2=new MyThread("线程b");
        mt1.start();
        mt2.start();
    }
}

2) Runnable接口

  在实际开辟中一个多线程的操作很少 使用Thread类,而是通过Runnable接口实现 。 public interface Runnable{ public void run(); }
例子:

class MyThread implements Runnable{
    private String name;
    public MyThread(String name) {
        this.name = name;
    }
    public void run(){
        for(int i=0;i<100;i++){
            System.out.println("线程开端:"+this.name+",i="+i);
        }
    }
};

  然而在Runnable的子类中没有start() 方法,只有Thread类中才有 。此时视察Thread类,有一个构造函数:public Thread(Runnable targer) 此构造函数接受Runnable的子类实例,也就是说可以通过Thread类来启动Runnable实现多线程 。(start() 可以协调系统的资源):

public class ThreadDemo01 {
    public static void main(String[] args) {
        MyThread mt1=new MyThread("线程a");
        MyThread mt2=new MyThread("线程b");
        new Thread(mt1).start();
        new Thread(mt2).start();
    }
}

3)实际中如何应用这两种实现模式
  在程序实现多线程应优先以实现Runnable接口为主,由于实现Runnable接口相比继承Thread类有如下好处:
1.避免点继承的局限,一个类可以继承多个接口 。
2. 利于资源的共享。
以卖票程序为例,通过Thread类实现:

class MyThread extends Thread {
    private int ticket=10;
    public void run(){
        for(int i=0;i<20;i++) {
            if(this.ticket>0){
                System.out.println("卖票:ticket"+this.ticket--);
            }
        }
    }
};     

下面通过三个线程对象,同时卖票:

public class ThreadTicket {
    public static void main(String[] args) {
        MyThread mt1=new MyThread();
        MyThread mt2=new MyThread();
        MyThread mt3=new MyThread();
        mt1.start();//每个线程都各卖了10张,共卖了30张票
        mt2.start();//但实际只有10张票,每个线程都卖自己的票
        mt3.start();//没有达到资源共享
    }
}

  假如用Runnable就 可以实现资源共享,下面看例子:

class MyThread implements Runnable{
    private int ticket=10;
    public void run(){
        for(int i=0;i<20;i++){
            if(this.ticket>0){
                System.out.println("卖票:ticket"+this.ticket--);
            }
        }
    }
}


public class RunnableTicket {
public static void main(String[] args) {
    MyThread mt=new MyThread();
    new Thread(mt).start();//同一个mt
    new Thread(mt).start();
    new Thread(mt).start();
}
};

  现在程序中有三个线程,然而一共卖了10张票,也就是说使用Runnable实现多线程可以达到资源共享的目的。

4)Runnable接口和Thread的关系总结
   (1) 说白了就是类和接口的区别。Thread是一个类,java中是不允许继承多个父类的,这就是Thread的一个局限性。而使用Runnable就不同了,可以implements多个接口,同时继承一个父类,这样会更加灵活。
   (2) 当多个线程需要共享资源时,用Thread很难达到目的,但是用Runnable接口就容易许多了。
  (3) 二者的联系:看源码可以发现,Thread其实就是继承了Runnable接口的子类。

取消线程
  有时,当一个组件完成或被杀死是,开发者希望有它产生的线程也同样被杀死,例如在某个Acitivity中定义了线程:
  private …Thread myThread;
myThread.stop()方法已经被弃用了,因为它会将应用程序置于不可预知的状态,取而代之的是下面的方法,比如在父组件的onStop()方法中加入

if(myThread != null){
    Thread dummy = myThread;
    myThread = null;
    dummy.interrupt();
}

在应用程序层面上还有另外一种方法来完成相同的工作:使用setDaemon(true)方法将所有生成的线程都声明为守护线程,可以确保所有与应用程序关联的线程在应用程序的主线程终结时,也随之被杀死。

//use when initially starting a thread
myThread。setDaemon(true);
myThread.start();

设置线程的优先级
  Android系统会处理线程的优先级,默认情况下,一个新线程,如myThread,其优先级被定为5。开发者可以在myThread.start()执行之前,通过调用myThread.setPriority(priority)来为线程设定另外的优先级。优先级不能高于Thread.MAX_PRIORITY(10)或者低于Thread.MIN_PRIORITY(1)
  Android还提供了另一种设定线程优先级的方法通过android.os.Process.setThreadPriority (int tid, int priority)

priority:【-20, 19】,高优先级 -> 低优先级。在实际操作中,因为setThreadPriority 是一个基于“良好的”Linux值得优先级,可以设定的粒度更细,并且对线程的影响也更加明显。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值