Heim > Java > JavaBase > Detaillierte Erläuterung des Java-Thread-Pools

Detaillierte Erläuterung des Java-Thread-Pools

angryTom
Freigeben: 2019-11-26 15:44:48
nach vorne
3423 Leute haben es durchsucht

Detaillierte Erläuterung des Java-Thread-Pools

Thread-Pool-Übersicht

1. Ein Thread-Pool ist ein Pool, der Threads verwaltet, wodurch die Erstellung reduziert werden kann und Zerstörung von Threads.

Da ein Thread tatsächlich ein Objekt ist, müssen Sie den Klassenladeprozess durchlaufen, ein Objekt zerstören und die GC-Garbage Collection durchlaufen Prozesse, die alle einen Ressourcenaufwand erfordern.

2. Wenn die Aufgabe eintrifft, ist das Erstellen des Threads definitiv viel langsamer

3. Legen Sie den Thread wieder in den Pool, nachdem er aufgebraucht ist, um den Effekt der Wiederverwendung zu erzielen

(empfohlenes Video: Java-Video-Tutorial)

Thread-Pool Ausführung

Metapher

Kernthreads werden mit regulären Mitarbeitern des Unternehmens verglichen

Nicht-Kernthreads werden mit ausgelagerten Mitarbeitern verglichen

Blockierungswarteschlangen werden mit Nachfragepools verglichen

Einreichen von Aufgaben wird mit Einreichungsanforderungen verglichen

Detaillierte Erläuterung des Java-Thread-Pools

Formelle Ausführung

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit,
   BlockingQueue<Runnable> workQueue,
   ThreadFactory threadFactory,
   RejectedExecutionHandler handler)
Nach dem Login kopieren
corePoolSize     核心线程数
maximumPoolSize  线程池最大线程数
keepAliveTime    空闲线程存活时间
TimeUnit         线程空闲存活时间单位
workQueue        存放任务的阻塞队列
threadFactory    线程工厂
handler          饱和策略
Nach dem Login kopieren

● Einreichen Eine Aufgabe und wenn die Anzahl der überlebenden Kernthreads im Thread-Pool geringer ist als die Anzahl der Threads corePoolSize, erstellt der Thread-Pool einen Kernthread zur Bearbeitung übermittelter Aufgaben.

● Wenn die Anzahl der Kernthreads im Thread-Pool voll ist, d. h. die Anzahl der Threads gleich corePoolSize ist, wird eine neu übermittelte Aufgabe in die Aufgabenwarteschlange workQueue gestellt und zur Ausführung in die Warteschlange gestellt.

● Wenn die Anzahl der verbleibenden Threads im Thread-Pool gleich corePoolSize ist und die Aufgabenwarteschlange workQueue ebenfalls voll ist, ermitteln Sie, ob die Anzahl der Threads MaximumPoolSize erreicht, dh ob die maximale Anzahl von Threads erreicht ist Wenn nicht, erstellen Sie einen Nicht-Kern-Thread, der die übermittelte Aufgabe ausführt.

● Wenn die aktuelle Anzahl der Threads die maximale PoolSize erreicht und neue Aufgaben kommen, wird die Ablehnungsrichtlinie direkt verwendet.

Mehrere Sättigungsstrategien

AbortPolicy         抛出一个异常,默认的
DiscardPolicy       直接丢弃任务
DiscardOldestPolicy 丢弃队列里最老的任务,将当前这个任务继续提交给线程池
CallerRunsPolicy    交给线程池调用所在的线程进行处理
Nach dem Login kopieren

Thread-Pool-Ausnahmebehandlung

Aufgrund des Auftretens von Thread-Verarbeitungsaufgaben beim Aufrufen des Thread-Pools Ausnahmen werden möglicherweise vom Thread-Pool abgefangen, sodass die Ausführung der Aufgabe möglicherweise nicht bekannt ist. Daher müssen wir Thread-Pool-Ausnahmen berücksichtigen.

Methode eins:

@Test
public void test1() throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 5; i++) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("name: " + Thread.currentThread().getName());
                    Object a = null;
                    System.out.println(a.hashCode());
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        });
    }
}
Nach dem Login kopieren

Methode zwei:

@Test
public void test2() throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 20; i++) {
        Future<?> future = executorService.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("name: " + Thread.currentThread().getName());
                Object a = null;
                System.out.println(a.hashCode());
            }
        });
        try {
            future.get();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
Nach dem Login kopieren

Arbeitswarteschlange des Thread-Pools

● ArrayBlockingQueue

● LinkedBlockingQueue

● SynchronousQueue

● DelayQueue

● PriorityBlockingQueue

==ArrayBlockingQueue==

● Initialisiert ein Array eines bestimmten Kapazität

● Standardmäßig wird eine unfaire Sperre verwendet. Der gegenseitige Ausschluss ist nicht möglich hinzugefügt, bis ein Element entfernt wurde

● Öffnen Sie bei der Verwendung einen kontinuierlichen Speicher. Wenn die Initialisierungskapazität zu groß ist, führt dies leicht zu einer Verschwendung von Ressourcen hinzufügen.

==LinkedBlockingQueue==

● Verknüpfte Listendatenstruktur verwenden

● Nicht zusammenhängender Speicherplatz

● Zur Steuerung zwei wiedereintrittsfähige Sperren verwenden Der Ein- und Ausstieg von Elementen und die Verwendung von Condition zum Aufwecken und Ausschließen zwischen Threads.

● ist begrenzt. In der Standardkonstruktionsmethode ist die Kapazität Integer.MAX_VALUE

= =SynchronousQueue==

● Die interne Kapazität beträgt 0

● Jeder Löschvorgang muss auf den Einfügevorgang warten

● Jeder Einfügevorgang muss auf den Löschvorgang warten

● Sobald für ein Element ein Einfügungsthread und ein Entfernungsthread vorhanden sind, wird dieser schnell an den Entfernungsthread übergeben. Dieser Container entspricht einem Kanal und speichert keine Elemente selbst

● In einer Multi-Task-Warteschlange ist dies der schnellste Weg, Aufgaben zu verarbeiten.

==PriorityBlockingQueue==

● Grenzenloses Design, aber die Kapazität hängt tatsächlich von den Systemressourcen ab

● Elemente hinzufügen, wenn mehr als 1, geben Sie die Prioritätssortierung ein

==DelayQueue==

● Randloses Design

● Das Hinzufügen (Put) blockiert nicht, das Entfernen der Blockierung

● Elemente haben eine Ablaufzeit

● Nur abgelaufene Elemente werden herausgenommen

Häufig verwendete Thread-Pools

● newFixedThreadPool (Thread-Pool mit einer festen Anzahl von Threads)

● newCachedThreadPool (Thread-Pool, der Threads zwischenspeichern kann)

● newSingleThreadExecutor (Single-Threaded-Thread-Pool)

● newScheduledThreadPool (Thread-Pool für geplante und periodische Ausführung)

==newFixedThreadPool ==

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
Nach dem Login kopieren

Funktionen

1. Die Anzahl der Kernthreads entspricht der maximalen Anzahl von Threads

Es gibt keine solche Ding als nicht Die Leerlaufzeit, also keepAliveTime, ist 0

3. Die Blockierungswarteschlange ist eine unbegrenzte Warteschlange LinkedBlockingQueue

Arbeitsmechanismus:

Detaillierte Erläuterung des Java-Thread-Pools● Senden Sie die Aufgabe


● Wenn die Anzahl der Threads geringer ist als der Kernthread, erstellen Sie einen Kernthread, um die Aufgabe auszuführen

● Wenn die Anzahl der Threads dem Kernthread entspricht, fügen Sie die Aufgabe zur Blockierungswarteschlange LinkedBlockingQueue hinzu

● 如果线程执行完任务,去阻塞队列取任务,继续执行。

==newCachedThreadPool==

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}
Nach dem Login kopieren

线程池特点

● 核心线程数为0

● 最大线程数为Integer.MAX_VALUE

● 阻塞队列是SynchronousQueue

● 非核心线程空闲存活时间为60秒

Detaillierte Erläuterung des Java-Thread-Pools

工作机制:

● 提交任务

● 因为没有核心线程,所以任务直接加到SynchronousQueue队列。

● 判断是否有空闲线程,如果有,就去取出任务执行。

● 如果没有空闲线程,就新建一个线程执行。

● 执行完任务的线程,还可以存活60秒,如果在这期间,接到任务,可以继续活下去;否则,被销毁。

使用场景

用于并发执行大量短期的小任务。

使用SynchronousQueue作为工作队列,工作队列本身并不限制待执行的任务的数量。但此时需要限定线程池的最大大小为一个合理的有限值,而不是Integer.MAX_VALUE,否则可能导致线程池中的工作者线程的数量一直增加到系统资源所无法承受为止。

如果应用程序确实需要比较大的工作队列容量,而又想避免无界工作队列可能导致的问题,不妨考虑SynchronousQueue。SynchronousQueue实现上并不使用缓存空间

==newSingleThreadExecutor==

线程池特点

● 核心线程数为1

● 最大线程数也为1

● 阻塞队列是LinkedBlockingQueue

● keepAliveTime为0

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>(),
                                threadFactory));
}
Nach dem Login kopieren

工作机制

Detaillierte Erläuterung des Java-Thread-Pools

● 提交任务

● 线程池是否有一条线程在,如果没有,新建线程执行任务

● 如果有,讲任务加到阻塞队列

● 当前的唯一线程,从队列取任务,执行完一个,再继续取,一个人(一条线程)夜以继日地干活。

使用场景

适用于串行执行任务的场景,一个任务一个任务的执行

==newScheduledThreadPool==

线程池特点

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());
}
Nach dem Login kopieren

● 最大线程数为Integer.MAX_VALUE

● 阻塞队列是DelayedWorkQueue

● keepAliveTime为0

● scheduleAtFixedRate() :按某种速率周期执行

● scheduleWithFixedDelay():在某个延迟后执行

工作机制

● 添加一个任务

● 线程池中的线程从 DelayQueue 中取任务

● 线程从 DelayQueue 中获取 time 大于等于当前时间的task

● 执行完后修改这个 task 的 time 为下次被执行的时间

● 这个 task 放回DelayQueue队列中

scheduleWithFixedDelay

● 无论任务执行时间长短,都是当第一个任务执行完成之后,延迟指定时间再开始执行第二个任务

scheduleAtFixedRate

● 在任务执行时间小于间隔时间的情况下,程序以起始时间为准则,每隔指定时间执行一次,不受任务执行时间影响

● 当执行任务时间大于间隔时间,此方法不会重新开启一个新的任务进行执行,而是等待原有任务执行完成,马上开启下一个任务进行执行。此时,执行间隔时间已经被打乱

本文来自php中文网,java教程栏目,欢迎学习!

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Java-Thread-Pools. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:cnblogs.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage