Einführung in HandlerThread

Einführung

HandlerThread  erbt von Thread und kapselt Looper intern . Nach dem Aufruf der Methode handlerThread.start() werden intern ein Looper und eine MessageQueue erstellt .Wir instanziieren einen Handler über dieses Looper- Objekt und können diesen Handler dann in anderen Threads  verwenden .
1. Verwenden Sie die herkömmliche Thread + Handler-Methode, um die Kommunikation zwischen Threads zu realisieren
Wir müssen das Looper-Objekt selbst implementieren und dann ein Handler-Objekt in der Looper-Schleife erstellen, um die Handler-Nachricht zu erhalten und die entsprechende Aufgabe auszuführen.
public Handler threadHandler;
new Thread(new Runnable() {
    @Override
    public void run() {
        Looper.prepare();
        threadHandler = new Handler(Looper.myLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                // 处理消息,因为这个方法是在子线程调用,所以要在这执行耗时任务
            }
        };
        Looper.loop();
    }
}).start();

2. Verwenden Sie HandlerThread, um die Kommunikation zwischen Threads zu realisieren

Erstellen Sie einfach zuerst eine HandlerThread- Instanz, rufen Sie dann handlerThread.start() auf, um ein Looper-  Objekt zu erstellen  , rufen Sie dann das Looper- Objekt in HandlerThread  über handlerThread.getLooper() ab und erstellen Sie unseren Handler basierend auf diesem Looper -Objekt,  um die Sub-Threads Business zu verarbeiten Logik.
HandlerThread handlerThread = new HandlerThread("handler-thread");
handlerThread.start(); // 必须在Handler创建前调用,因为线程start后才会创建Looper
Handler threadHandler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        // 处理消息,在子线程调用,所以要在这执行耗时任务

    }
};

Realisierungsprinzip

public class HandlerThread extends Thread {
    int mPriority;  // 线程优先级
    int mTid = -1;  // 线程Id
    Looper mLooper; // Looper循环器对象
    private @Nullable Handler mHandler;  // Handler 对象

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

    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    /**
     * 开启Looper循环之前的准备工作
     * 复写之后,添加自己的逻辑
     */
    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;
    }
    
    /**
     * 此方法返回与此线程关联的循环器。如果这个线程没有启动或者
     * 因为任何原因isAlive()返回false,这个方法将返回null。
     * 如果这个线程已经启动,这个方法将阻塞,直到循环器初始化为止。
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        // 如果线程已经启动,则会等待,直到创建了循环器。
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    /**
     * 返回一个已经与此线程进行关联的 Handler对象。
     */
    @NonNull
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }

    /**
     * 这是退出循环器Looper的方法,一旦调用了quit()方法,消息队列中的消息将会立即停止处理,
     * 并且之后发来的所有消息都会失败。比如sendMessage()方法会返回false。
     * 这是不安全的一种退出方式。即不管是否正在处理消息,直接移除所有回调。
     */
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    /**
     * 安全的退出Looper循环,
     * 会等待正在处理的消息处理完后再退出。
     */
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    /**
     * 获取线程Id
     */
    public int getThreadId() {
        return mTid;
    }
}

Priorität Priorität in HandlerThread

Weisen Sie dem HandlerThread- Thread vernünftigerweise die Priorität zu und optimieren Sie den Thread bis zu einem gewissen Grad.
Seine Standardpriorität ist: process.THREAD_PRIORITY_DEFAULT , dessen Wert "0" ist .
Der Wertebereich der Priorität ist "-20 bis 19", je kleiner der Wert, desto höher die Priorität. Threads mit höherer Priorität erhalten mehr CPU-Ressourcen und umgekehrt. Es ist jedoch nicht erforderlich, für HandlerThread eine so hohe Priorität wie für einen Worker-Thread festzulegen , daher müssen wir eine angemessene Prioritätsstufe entsprechend unseren Anforderungen festlegen.

HandlerThread-Verwendungsszenarien

Da es Looper kapselt  , gehört es zur Thread + Looper- Szene. Führen Sie zeitaufwändige Aufgaben und Multitasking-Operationen in Unterthreads aus.
Für lokale IO-Operationen :
HandlerThread kann verwendet werden, um lokale E/A-Lese- und Schreibvorgänge zu verarbeiten, da die meisten lokalen E/A-Vorgänge Millisekunden dauern, sodass für HandlerThread, eine Form von Einzelthread + Warteschlange, keine Blockierung auftritt. Wir können auch die Methode postAtFrontQueue() verwenden, um die lokale E/A zu lesen, wodurch die Leseoperation schnell zur Ausführung an den Anfang der Warteschlange gestellt werden kann. Zum Beispiel: Daten aus der Datenbank lesen und in der ListView-Liste anzeigen.
Nicht für Netzwerk-IO-Operationen:
Da HandlerThread eine synchrone Singlethread-Warteschlange ist, ist sie nicht für die Verarbeitung von Netzwerk-E/A-Vorgängen geeignet.  
Vor- und Nachteile von HandlerThread
Vorteile : Es kann nur ein Thread gestartet werden, um mehrere Aufgaben auszuführen.
Nachteile : Obwohl Multitasking unterstützt wird, ist HandlerThread synchron und kann keine Parallelität erreichen.
           Wenn also die Ausführung einer der Thread-Aufgaben zu lange dauert, werden nachfolgende Aufgaben verzögert.
Vorsichtsmaßnahmen
Wenn der HandlerThread mit der Verwendung fertig ist, müssen Sie seine Methode quitSafe() oder quit() aufrufen, um den Thread zu beenden.
quitSafe() wartet darauf, dass die verarbeitete Nachricht verarbeitet wird, bevor es beendet wird;
quit() entfernt alle Rückrufe direkt, unabhängig davon, ob die Nachricht verarbeitet wird oder nicht.

Supongo que te gusta

Origin blog.csdn.net/m0_49508485/article/details/127255505
Recomendado
Clasificación