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

来源:互联网 发布:win10如何更改mac地址 编辑:程序博客网 时间:2024/05/21 07:06

  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-1004-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-1104-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): mThreadTest04-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 threadmyThread。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值得优先级,可以设定的粒度更细,并且对线程的影响也更加明显。

0 0
原创粉丝点击