>  기사  >  백엔드 개발  >  HandlerThread 소스 코드 자세한 Android 예제

HandlerThread 소스 코드 자세한 Android 예제

php中世界最好的语言
php中世界最好的语言원래의
2017-12-20 11:47:191603검색

오늘 제가 가져온 글은 안드로이드에서 HandlerThread의 사용법과 단계를 예제코드를 통해 분석한 내용입니다. 필요하신 분들은 참고하시면 됩니다.

HandlerThread 소개:
우리는 Thread 스레드가 일회성 소비자 제품이라는 것을 알고 있습니다. Thread 스레드가 시간이 많이 걸리는 작업을 완료하면 스레드가 자동으로 삭제됩니다. 지금 수행해야 하는 시간이 많이 걸리는 또 다른 작업이 있는 경우 시간이 많이 걸리는 작업을 수행하기 위해 스레드를 다시 생성해야 합니다. 그러나 성능 문제가 있습니다. 스레드를 여러 번 생성하고 삭제하면 시스템 리소스가 소모됩니다. 이 문제를 이해하기 위해 우리는 루프 스레드 Looper Thread를 직접 구축할 수 있습니다. 시간이 많이 걸리는 작업이 루프 스레드에 배치되면 스레드는 시간이 많이 걸리는 작업을 실행하고 루프 스레드는 대기 상태에 있게 됩니다. 시간이 많이 걸리는 다음 작업이 시작될 때까지 상태를 유지합니다. 이러한 방식으로 Thread 스레드를 여러 번 생성함으로써 발생하는 성능 문제를 피할 수 있습니다. 루프 스레드를 직접 구축할 수도 있지만, 실제로 Aandroid SDK

에 루프 스레드 프레임워크가 있다는 사실을 알려드립니다. 이 시점에서는 사용법을 익히기만 하면 됩니다. 그게 전부입니다! 물론 오늘의 주인공은 HandlerThread 입니다! 다음으로 HandlerThread를 해보자 박수~~

HandlerThread의 상위 클래스는 Thread이므로 HandlerThread는 실제로 스레드이지만 내부적으로 Looper 루프를 구현하는 데 도움이 될 뿐입니다. 그럼 먼저 핸들러 사용법을

알아보겠습니다!

HandlerThread 사용 단계:

1. 인스턴스 개체 만들기

HandlerThread handlerThread = new HandlerThread("handlerThread");

위 매개변수는 임의의
문자열

일 수 있습니다. 매개변수의 주요 기능은 현재 스레드의 이름을 표시하는 것입니다.

2. HandlerThread 스레드 시작

handlerThread.start();

이 시점에서 루프 스레드 구축이 완료되었습니다. 그렇다면 시간이 많이 걸리는 비동기 작업을 실행하기 위해 HandlerThread 스레드에 어떻게 넣을 수 있는지 궁금할 것입니다. 물론 방법이 있습니다. 세 번째 부분을 살펴보겠습니다.

3. 루프 메시지 처리 메커니즘 구축

Handler subHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
      @Override
      public boolean handleMessage(Message msg) {
        //实现自己的消息处理
        return true;
      }
    });


세 번째 단계는 Handler 객체를 생성하고 위 HandlerThread의 루퍼 객체를 Handler 매개변수로 사용한 다음 Handler의

handlerMessage 메소드를 다시 작성하는 것입니다. 콜백 인터페이스 클래스. 시간이 많이 걸리는 작업을 처리합니다.

요약: 위의 세 단계의 순서는 어긋날 수 없으며, 단계를 엄격히 따라야 합니다. 이 시점에서 우리는 subHandler를 호출하여 실행을 위해

메시지 보내기
형식으로 스레드

HandlerThread에 시간이 많이 걸리는 작업을 보낼 수 있습니다. 이는 subHandler의 콜백 인터페이스 클래스에 있는 handlerMessage 메소드가 실제로 작업자 스레드에서 실행된다는 의미입니다.

HandlerThread 인스턴스:

package com.example.handlerthread;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
  private Handler mSubHandler;
  private TextView textView;
  private Button button;
 
  private Handler.Callback mSubCallback = new Handler.Callback() {
    //该接口的实现就是处理异步耗时任务的,因此该方法执行在子线程中
    @Override
    public boolean handleMessage(Message msg) {
 
      switch (msg.what) {
      case 0:
        Message msg1 = new Message();
        msg1.what = 0;
        msg1.obj = java.lang.System.currentTimeMillis();
        mUIHandler.sendMessage(msg1);
        break;
 
      default:
        break;
      }
 
      return false;
    }
  };
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    textView = (TextView) findViewById(R.id.textView);
    button = (Button) findViewById(R.id.button);
 
    HandlerThread workHandle = new HandlerThread("workHandleThread");
    workHandle.start();
    mSubHandler = new Handler(workHandle.getLooper(), mSubCallback);
 
    button.setOnClickListener(new OnClickListener() {
 
      @Override
      public void onClick(View v) {
        //投放异步耗时任务到HandlerThread中
        mSubHandler.sendEmptyMessage(0);
      }
    });
 
  }
}

HandlerThread 소스 코드 분석

HandlerThread

Construction method


/**
 * Handy class for starting a new thread that has a looper. The looper can then be
 * used to create handler classes. Note that start() must still be called.
 */
public class HandlerThread extends Thread {
  //线程优先级
  int mPriority;
  //当前线程id
  int mTid = -1;
  //当前线程持有的Looper对象
  Looper mLooper;
   
  //构造方法
  public HandlerThread(String name) {
    //调用父类默认的方法创建线程
    super(name);
    mPriority = Process.THREAD_PRIORITY_DEFAULT;
  }
  //带优先级参数的构造方法
  public HandlerThread(String name, int priority) {
    super(name);
    mPriority = priority;
  }
...............
}


Analytic: 이 클래스는 시작 부분에 설명을 제공합니다. 오페라를 만들다 루핑 스레드의 경우 Looper 객체는 Handler 객체를 생성하는 데 사용됩니다. Handler

객체를 생성하기 전에 스레드를 시작하려면 start() 메서드를 호출해야 한다는 점은 주목할 가치가 있습니다. 어쩌면 여기 질문이 있는 분들도 계시겠죠? 핸들러를 생성하기 전에 start() 메서드를 호출해야 하는 이유는 무엇입니까? 이에 대해서는 나중에 답변해 드리겠습니다.

위의 코드 주석은 매우 명확합니다. HandlerThread 클래스에는 두 개의 생성자가 있습니다. 차이점은 현재 스레드의 우선 순위 매개 변수를 설정한다는 것입니다. 자신의 상황에 따라 우선순위


를 설정하거나 기본 우선순위를 사용할 수 있습니다.

HandlerThrad의 실행 메소드

public class HandlerThread extends Thread {
 /**
   * Call back method that can be explicitly overridden if needed to execute some
   * setup before Looper loops.
   */
  protected void onLooperPrepared() {
  }
 
  @Override
  public void run() {
    //获得当前线程的id
    mTid = Process.myTid();
    //准备循环条件
    Looper.prepare();
    //持有锁机制来获得当前线程的Looper对象
    synchronized (this) {
      mLooper = Looper.myLooper();
      //发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait
      notifyAll();
    }
    //设置当前线程的优先级
    Process.setThreadPriority(mPriority);
    //该方法实现体是空的,子类可以实现该方法,作用就是在线程循环之前做一些准备工作,当然子类也可以不实现。
    onLooperPrepared();
    //启动loop
    Looper.loop();
    mTid = -1;
  }
}

분석: 위 코드의 주석은 매우 명확하게 작성되었습니다. 위 실행 메소드의 주요 기능은 Looper.prepare 및 Looper.loop를 호출하여 루프 스레드를 작성하는 것입니다. onLooperPrepared 메소드는 run 메소드에서 루프를 시작하기 전에 호출된다는 점을 언급할 가치가 있습니다. 이 메소드의 구현은 비어 있으며 사용자는 하위 클래스에서 이 메소드를 구현할 수 있습니다. 이 메서드의 목적은 스레드 루프 전에 일부 초기화 작업을 수행하는 것입니다. 물론 필요에 따라 이 메서드를 구현할 필요는 없습니다. Google 엔지니어들도 코드를 작성할 때 코드의 확장성을 고려한다는 것을 알 수 있습니다. 대단해요!

HandlerThread의 다른 메소드

getLooper는 현재 스레드의 Looper 객체를 가져옵니다

/**
   * This method returns the Looper associated with this thread. If this thread not been started
   * or for any reason is isAlive() returns false, this method will return null. If this thread
   * has been started, this method will block until the looper has been initialized.
   * @return The looper.
   */
  public Looper getLooper() {
    //如果线程不是存活的,则直接返回null
    if (!isAlive()) {
      return null;
    }
     
    // If the thread has been started, wait until the looper has been created.
    //如果线程已经启动,但是Looper还未创建的话,就等待,知道Looper创建成功
    synchronized (this) {
      while (isAlive() && mLooper == null) {
        try {
          wait();
        } catch (InterruptedException e) {
        }
      }
    }
    return mLooper;
  }

분석: 사실 메소드 시작 부분에 있는 영어 주석에서 매우 명확하게 설명했습니다. 이 메서드의 기능은 스레드에서 현재 HandlerThread mLooper 개체를 가져오는 것입니다.

먼저 현재 스레드가 살아 있는지 확인합니다. 살아 있지 않으면 바로 null을 반환합니다. 둘째, 현재 스레드가 남아 있으면 스레드의 멤버 변수 mLooper가 null인지 확인합니다.

null이면 현재 스레드가 성공적으로 생성되었지만 Looper 개체를 생성할 시간이 없다는 의미입니다. 여기에서 wait 메소드가 호출되어 대기합니다. run 메소드의 informAll 메소드가 호출된 후 현재 스레드의 wait 메소드에 종료를 기다리라고 알리고 루프에서 빠져나와 mLooper의 값을 얻습니다. 물체.

总结:在获得mLooper对象的时候存在一个同步的问题,只有当线程创建成功并且Looper对象也创建成功之后才能获得mLooper的值。这里等待方法wait和run方法中的notifyAll方法共同完成同步问题。

quit结束当前线程的循环

/**
   * Quits the handler thread's looper.
   * <p>
   * Causes the handler thread&#39;s looper to terminate without processing any
   * more messages in the message queue.
   * </p><p>
   * Any attempt to post messages to the queue after the looper is asked to quit will fail.
   * For example, the {@link Handler#sendMessage(Message)} method will return false.
   * </p><p class="note">
   * Using this method may be unsafe because some messages may not be delivered
   * before the looper terminates. Consider using {@link #quitSafely} instead to ensure
   * that all pending work is completed in an orderly manner.
   * </p>
   *
   * @return True if the looper looper has been asked to quit or false if the
   * thread had not yet started running.
   *
   * @see #quitSafely
   */
  public boolean quit() {
    Looper looper = getLooper();
    if (looper != null) {
      looper.quit();
      return true;
    }
    return false;
  }
//安全退出循环
 public boolean quitSafely() {
    Looper looper = getLooper();
    if (looper != null) {
      looper.quitSafely();
      return true;
    }
    return false;
  }

   


分析:以上有两种让当前线程退出循环的方法,一种是安全的,一中是不安全的。至于两者有什么区别? quitSafely方法效率比quit方法标率低一点,但是安全。具体选择哪种就要看具体项目了。

总结:

1.HandlerThread适用于构建循环线程。

2.在创建Handler作为HandlerThread线程消息执行者的时候必须调用start方法之后,因为创建Handler需要的Looper参数是从HandlerThread类中获得,而Looper对象的赋值又是在HandlerThread的run方法中创建。


相信看了这些案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

相关阅读:

php如何实现栈数据结构以及括号匹配算法的代码示例详解

php中最简单的字符串匹配算法,php匹配算法_PHP教程

最简单的php中字符串匹配算法教程

위 내용은 HandlerThread 소스 코드 자세한 Android 예제의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.