Android 의 스 레 드 와 스 레 드 풀 분석

머리말
내용 이 너무 많 기 때문에 상하 두 부분 으로 나 눌 것 입 니 다.첫 번 째 부분 은 주로 안 드 로 이 드 의 스 레 드 와 안 드 로 이 드 에서 자주 사용 하 는 스 레 드 풀 에 대해 이야기 할 것 입 니 다.두 번 째 부분 에 서 는 AsyncTask 의 사용 과 작업 원 리 를 함께 알 아 보 겠 습 니 다.
HandlerThread
HandlerThread 는 Thread 의 하위 클래스 로 Handler 를 사용 할 수 있 는 Thread 로 실현 이 간단 합 니 다.우 리 는 그것 의 소스 코드 를 보 자.

package android.os;

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }


      public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }


       protected void onLooperPrepared() {
    }



    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }



     public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }



       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;
    }




     public int getThreadId() {
        return mTid;
    }
}
여러분 에 게 똑똑히 보 여 드 리 기 위해 서,우리 의 원본 코드 의 일부 영어 주석 이 제거 되 었 는데,지금 은 매우 뚜렷 해 졌 다.전체 유형 에서 구조 방법 과 대외 적 으로 몇 가지 Public 방법 을 제공 하 는 것 을 제외 하고 run()만 남 았 다.그것 의 실현 을 보면 일반적인 Thread 실현 과 별 차이 가 없다.모두 run()방법 에서 시간 소모 작업 을 수행 합 니 다.그러나 HandlerThread 내부 에 메시지 대기 열 을 만 들 었 고 run()방법 은 무한 순환 방법 입 니 다.HandlerThread 가 필요 하지 않 을 때 quitSafely()나 quit()방법 으로 이 스 레 드 를 끝 낼 수 있 습 니 다.이것 은 비교적 편리 하 다.
IntentService
IntentService 는 특수 한 Service 로 Service 의 하위 클래스 이 며 추상 적 인 클래스 이기 때문에 하위 클래스 를 만들어 야 Intent Service 를 사용 할 수 있 습 니 다.Intent Service 는 배경 작업 을 수행 하 는 데 사용 할 수 있 습 니 다.작업 이 완료 되면 스스로 끝 납 니 다.수 동 으로 끝 낼 필요 가 없습니다.여기 서 주의해 야 할 문 제 는 Intentservice 에 스 레 드 가 내장 되 어 있 지만 Service 에 속 하기 때문에 우선 순위 가 스 레 드 보다 훨씬 높 기 때문에 시스템 에 의 해 쉽게 죽 이지 않 습 니 다.우선 순위 가 높 은 임 무 를 수행 하 는 것 이 좋 습 니 다.원본 코드 보기:

package android.app;

import android.annotation.WorkerThread;
import android.annotation.Nullable;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;



public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;



    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }



        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }




    public IntentService(String name) {
        super();
        mName = name;
    }




   public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }




    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }




      @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }




    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }




    public IBinder onBind(Intent intent) {
        return null;
    }




    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}
이곳 은 간단 하 다.이런 방법 들 은 서 비 스 를 자주 사용 하 는 친구 들 에 게 익숙 하 다.여러분,onCreate()방법 을 보 세 요.맞습니다.인 텐 트 서 비 스 는 Handler Thread 와 Handler 를 봉 인 했 습 니 다.
IntentService 가 onCreate()를 시작 하면 방법 이 호출 되 고 HandlerThread 와 ServiceHandler 를 만 듭 니 다.한편,onStart Command()방법 은 onStart()방법 을 호출 했다.onStart()방법 을 통 해 알 수 있 듯 이 IntentService 는 ServiceHandler 를 통 해 메 시 지 를 보 내 는 것 일 뿐 이 메 시 지 는 Handler Thread 에서 처 리 될 것 이다.
이 onStart()방법 을 보 세 요.intent 를 메시지 로 onHandleIntent 에 전달 합 니 다.이 intent 는 보통 우리 가 전달 하 는 데이터 입 니 다.온 핸드 인 텐트 는 이 인 텐트 를 통 해 구체 적 인 백 스테이지 임 무 를 구별 하 는 것 이다.
자,AsyncTask 의 사용 과 작업 원리.우 리 는 다음 장 에서 말 할 것 이다.다음은 스 레 드 탱크 를 봅 시다.
모두 가 이런 상황 을 만난 적 이 있 는 지 모르겠다.우 리 는 프로젝트 를 쓰 고 있 습 니 다.시간 이 걸 릴 때 어떻게 해 야 합 니까?new Thread().start 가 아 닙 니까?그러면 전체 프로젝트 에 new 몇 개의 Thread 가 필요 합 니까?이런 것 은 분명히 성능 을 낭비 하 는 것 이다.스 레 드 도 좋 은 자원 이 니까.그렇다면 스 레 드 를 재 활용 할 수 있 는 방법 은 없 을 까?정 답 은 스 레 드 탱크 다.
스 레 드 탱크 의 장점
1.스 레 드 탱크 의 스 레 드 를 다시 사용 하여 스 레 드 의 생 성 과 소각 으로 인 한 성능 비용 을 피한다.
2.스 레 드 탱크 의 스 레 드 병발 수 를 효과적으로 제어 하고 대량의 스 레 드 간 에 서로 자원 을 선점 하기 때문에 발생 하 는 차단 현상 을 피 할 수 있 습 니 다.
3.라인 에 대해 간단 한 관 리 를 할 수 있 고 정시 집행 과 지정 한 간격 순환 집행 등 기능 을 제공 할 수 있다.
ThreadPoolExecutor
Android 의 스 레 드 탱크 개념 은 자바 에서 Executor,Executor 는 빈 인터페이스 이 고 진정한 스 레 드 탱크 는 Thread PoolExecutor 를 실현 합 니 다.

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
ThreadPoolExcutor 매개 변수의 의 미 를 간단하게 소개 합 니 다.
core PoolSize:스 레 드 탱크 의 핵심 스 레 드 수 입 니 다.기본 적 인 상황 에서 핵심 스 레 드 는 온라인 스 레 드 탱크 에서 계속 살아 남 습 니 다.설령 그들 이 방치 상태 에 있 더 라 도.Thread PoolExecutor 의 allow CoreThreadTimeOut 속성 을 true 로 설정 하면 유 휴 된 핵심 스 레 드 가 새로운 작업 을 기다 리 고 있 을 때 keepAliveTime 이 설정 한 시간 을 초과 하면 핵심 스 레 드 가 회 수 됩 니 다.
maximumPoolSize:최대 스 레 드 탱크 가 수용 할 수 있 는 최대 스 레 드 수 를 설정 합 니 다.스 레 드 탱크 의 스 레 드 가 이 수 에 도달 하면 새 작업 이 막 힐 것 입 니 다.
keepAliveTime:비 핵심 스 레 드 수 방치 시간.
유닛:keepAliveTime 매개 변수의 시간 단 위 를 지정 합 니 다.
work Queue:스 레 드 탱크 의 작업 대기 열 입 니 다.
threadFactory:스 레 드 공장,스 레 드 탱크 에 새로운 스 레 드 를 만 드 는 기능 을 제공 합 니 다.
스 레 드 탱크 의 분류
Android 에서 흔히 볼 수 있 는 스 레 드 풀 은 Fixed ThreadPool,Cached ThreadPool,Scheduled ThreadPool,Single ThreadExecutor 네 가지 가 있 습 니 다.
FixedThreadPool
Fixed ThreadPool 스 레 드 풀 은 Executors 의 new Fixed ThreadPool 방법 으로 만 듭 니 다.그것 의 특징 은 이 스 레 드 탱크 의 스 레 드 수량 이 고정 되 어 있다 는 것 이다.스 레 드 가 유 휴 상태 에 있 더 라 도 스 레 드 탱크 가 닫 히 지 않 는 한 회수 되 지 않 습 니 다.모든 스 레 드 가 활성 상태 에 있 을 때 새 작업 은 대기 열 에서 스 레 드 를 기다 리 고 있 습 니 다.Fixed ThreadPool 은 핵심 스 레 드 만 있 고 비 핵심 스 레 드 는 없습니다.

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                            0L, TimeUnit.MILLISECONDS,
                            new LinkedBlockingQueue<Runnable>(),
                            threadFactory);
}
CachedThreadPool
Cached ThreadPool 스 레 드 풀 은 Executors 의 new Cached ThreadPool 을 통 해 만 들 어 졌 습 니 다.이것 은 스 레 드 수가 고정 되 지 않 은 스 레 드 탱크 입 니 다.핵심 스 레 드 가 없고 비 핵심 스 레 드 만 있 습 니 다.스 레 드 탱크 의 스 레 드 가 모두 활성 상태 에 있 으 면 새로운 스 레 드 를 만들어 새로운 작업 을 처리 합 니 다.그렇지 않 으 면 유 휴 스 레 드 를 이용 하여 새로운 임 무 를 처리 할 것 이다.스 레 드 탱크 의 스 레 드 는 모두 시간 초과 메커니즘 이 있 는데 이 시간 초과 메커니즘 은 시간 이 60s 이 고 이 시간 을 초과 하면 유 휴 스 레 드 는 회수 된다.이런 스 레 드 탱크 는 대량의 시간 을 소모 하 는 임 무 를 처리 하기에 적합 하 다.Cached ThreadPool 의 미 션 대기 열 은 기본적으로 비어 있 습 니 다.

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                60L, TimeUnit.SECONDS,
                                new SynchronousQueue<Runnable>());
}
ScheduledThreadPool
Scheduled ThreadPool 스 레 드 풀 은 Executors 의 new Scheduled ThreadPool 을 통 해 만 들 어 졌 습 니 다.핵심 스 레 드 는 고정 되 어 있 지만 비 핵심 스 레 드 수 는 고정 되 어 있 지 않 으 며 비 핵심 스 레 드 가 비어 있 으 면 바로 회수 되 었 습 니 다.이런 라인 은 정시 임 무 를 수행 하고 고정 주 기 를 가 진 중복 임 무 를 수행 하기에 적합 하 다.

public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }


public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue(), threadFactory);
    }
SingleThreadExecutor
SingleThreadExecutor 스 레 드 풀 은 Executors 의 new SingleThreadExecutor 방법 을 통 해 만 들 어 졌 습 니 다.이러한 스 레 드 풀 에는 하나의 핵심 스 레 드 만 있 고 비 핵심 스 레 드 도 없습니다.이 는 모든 작업 이 같은 스 레 드 에서 순서대로 실 행 될 수 있 도록 확보 합 니 다.그러면 스 레 드 동기 화 문 제 를 고려 할 필요 가 없습니다.

public static ExecutorService newSingleThreadExecutor() {

        return new FinalizableDelegatedExecutorService

            (new ThreadPoolExecutor(1, 1,

                                    0L, TimeUnit.MILLISECONDS,

                                    new LinkedBlockingQueue<Runnable>()));

    }
이상 은 안 드 로 이 드 의 스 레 드 와 스 레 드 탱크 의 상세 한 내용 을 분석 하 는 것 입 니 다.안 드 로 이 드 의 스 레 드 와 스 레 드 탱크 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기