So erstellen Sie einen Java-Thread-Pool
Die Vorteile des Thread-Pools
können die Wiederverwendung von Threads realisieren und das erneute Erstellen und Zerstören von Threads vermeiden. Das Erstellen und Zerstören von Threads ist für die CPU sehr kostspielig.
Sie können die maximale Anzahl der Threads begrenzen, die erstellt werden können, und die Thread-Pool-Parameter dynamisch an die Leistung Ihres eigenen Computers anpassen, um die Anwendungsleistung zu verbessern.
Bietet Funktionen wie geplante Ausführung und Parallelitätskontrolle.
Einheitliche Verwaltung von Threads.
Fünf Möglichkeiten, einen Thread-Pool zu erstellen
1: Cache-Thread-Pool (nicht empfohlen)
2: Thread-Pool mit fester Kapazität (nicht empfohlen)
3: Einzelner Thread-Pool (nicht empfohlen)
4: Timing Aufgaben-Thread-Pool (nicht empfohlen)
5: Erstellen Sie einen Thread-Pool über die ThreadPoolExecutor-Konstruktionsmethode (im Alibaba-Entwicklungshandbuch dringend empfohlen)
Die ersten vier Möglichkeiten zum Erstellen eines Thread-Pools werden alle über die statischen Methoden von Executors erstellt.
CachedThreadPool
ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int finalI = i; executorService.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); }
Warum wird der zwischengespeicherte Thread-Pool nicht empfohlen?
Quellcode-Analyse
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue()); }
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
Anhand der beiden oben genannten Codeausschnitte können wir sehen, dass die maximale PoolSize von CachedThreadPool der Maximalwert von Integer 2147483647 ist, was einer unbegrenzten Thread-Erstellung entspricht, und das Erstellen von Threads erfordert Speicher, was zu einem Speicherüberlauf führt , und normale Maschinen benötigen keinen so großen Speicher, um eine so große Anzahl von Threads zu erstellen.
Thread-Pool mit fester Kapazität FixedThreadPool
newFixedThreadPool(int num), num ist die feste Anzahl von Threads, die wir angeben möchten
ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) { final int finalI = i; executorService.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); }
Ausgabe:
pool-1-thread-5
run>4
pool- 1-thread-4run>3
pool-1-thread-5run>5
pool-1-thread-3run>2
pool- 1- thread-3run>8
pool-1-thread-3run>9
pool-1-thread-2run>1
pool-1- thread- 1run>0
pool-1-thread-5run>7
pool-1-thread-4run>6
Es ist zu sehen dass Threads zur Wiederverwendung verwendet werden.
Warum ist FixedThreadPool ein fester Thread-Pool?
Quellcode-Analyse
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); }
Aus diesem Quellcode ist ersichtlich, dass die Anzahl der Kern-Threads (corePoolSize) und die maximale Anzahl von Threads (maximumPoolSize) beide nThreads sind, da der Thread-Pool nur auf diese Weise nicht vorhanden ist erweitert und die Anzahl der Threads wird festgelegt.
Single-Thread-Pool SingleThreadExecutor
ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int finalI = i; executorService.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); }
Warum enthält SingleThreadExecutor nur einen Thread?
Quellcode-Analyse
public static ExecutorService newSingleThreadExecutor() { return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); }
Aus diesem Quellcode ist ersichtlich, dass die Anzahl der Kernthreads (corePoolSize) und die maximale Anzahl von Threads (maximumPoolSize) jeweils 1 sind, sodass nur ein Thread enthalten ist.
ScheduledThreadPool
int initDelay=10; //初始化延时 int period=1;//初始化延迟过了之后,每秒的延时 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"); } },initDelay,period, TimeUnit.SECONDS);
Die Wirkung dieses Codes ist: Warten Sie 10 Sekunden, nachdem das Programm ausgeführt wurde, geben Sie dann das erste Ergebnis aus und geben Sie das Ergebnis dann alle 1 Sekunde aus.
Warum wird ScheduledThreadPool nicht empfohlen?
Quellcode-Analyse
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, 2147483647, 10L, TimeUnit.MILLISECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue()); }
Es ist ersichtlich, dass die maximale Anzahl von Threads (maximumPoolSize) von ScheduledThreadPool dem Maximalwert von Integer 2147483647 entspricht, was einer unbegrenzten Thread-Erstellung entspricht, und das Erstellen von Threads erfordert Speicher, was zu einem Speicherüberlauf führt , und im Allgemeinen Die Maschine verwendet keinen so großen Speicher, um eine so große Anzahl von Threads zu erstellen.
ThreadPoolExecutor erstellt einen Thread-Pool (sehr zu empfehlen)
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); for (int i = 0; i < 12; i++) { final int finalI = i; threadPoolExecutor.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); }
Detaillierte Erklärung der sieben Parameter von ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { }
corePoolSize: die Anzahl der Kern-Threads. Sobald diese Threads erstellt wurden, werden sie nicht zerstört und bleiben immer bestehen. Der Thread-Pool verfügt standardmäßig über keine Threads. Wenn eine Aufgabe eintrifft, wird über ThreadFactory ein Thread erstellt, der immer vorhanden ist.
maximumPoolSize: Maximale Anzahl von Threads. Die Anzahl der Nicht-Kern-Threads = MaximumPoolSize-CorePoolSize. Die Anzahl der Nicht-Kern-Threads entspricht tatsächlich der Anzahl der skalierbaren Threads und kann zerstört werden.
keepAliveTime: Die Leerlaufzeit von Nicht-Kern-Threads. Wenn die Anzahl der durch die Erweiterung generierten Nicht-Kern-Threads nach der keepAliveTime immer noch im Leerlauf ist, werden diese Nicht-Kern-Threads zerstört.
Einheit: Zeiteinheit von keepAliveTime, zum Beispiel: Sekunden
workQueue: Wartebereich. Wenn eine Aufgabe > corePoolSize eintrifft, wird die Aufgabe in der blockierenden Warteschlange von workQueue gespeichert und wartet darauf, dass andere Threads sie verarbeiten.
threadFactory: Thread-Fabrik. Eine Möglichkeit, Threads zu erstellen.
Handler: Ablehnungsstrategie. Wenn es um > die maximale Anzahl von Threads + die Kapazität von workQueue geht, wird die Ablehnungsrichtlinie ausgeführt
workQueue
ArrayBlockingQueue: begrenzte Blockierungswarteschlange. Die Warteschlange hat eine Größenbeschränkung. Wenn die Kapazität überschritten wird, wird die Erweiterungs- oder Ablehnungsrichtlinie ausgelöst.
public ArrayBlockingQueue(int capacity) { this(capacity, false); }
LinkedBlockingQueue: Unbegrenzte Blockierungswarteschlange, die Warteschlange hat keine Größenbeschränkung und kann zu einem Speicherüberlauf führen.
public LinkedBlockingQueue() { this(2147483647); }
handler
AbortPolicy: Eine Ausnahme direkt auslösen
public static class AbortPolicy implements RejectedExecutionHandler { public AbortPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }
DiscardPolicy: Es wird keine Operation ausgeführt. Verwerfen Sie die Aufgabe stillschweigend.
public static class DiscardPolicy implements RejectedExecutionHandler { public DiscardPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } }
DiscardOldestPolicy: Verwerfen Sie die am längsten vorhandene Aufgabe
ThreadFactory threadFactory = Executors.defaultThreadFactory(); threadFactory.newThread(new Runnable() { @Override public void run() { System.out.println("threadFactory"); } }).start();
如何触发拒绝策略和线程池扩容?
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); for (int i = 0; i < 26; i++) { //并发数26 final int finalI = i; threadPoolExecutor.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI); } }); } /** * 核心线程数=10,最大线程数=20,故可扩容线程数=20-10 * BlockingQueue的大小为5,故等待区的大小为5,也就是当并发数<=核心线程数+5不会扩容,并发数大于16才会扩容 * * 触发扩容:并发数>核心线程数+阻塞队列的大小 * 对于这段代码,如果来了26个并发,10个并发会被核心线程处理,5个会在等待区,剩下11个会因为等待区满了而触发扩容 * 因为这里最多能够扩容10个,这里却是11个,所以会触发拒绝策略 */
为什么这段代码会触发拒绝策略
对于这段代码,如果来了26个并发,10个并发会被核心线程处理,5个会在等待区,剩下11个会因为等待区满了而触发扩容,但是又因为因为这里最多能够扩容10个,这里却是11个,所以会触发拒绝策略。
怎么触发扩容
触发扩容:并发数>核心线程数(corePoolSize)+阻塞队列(workQueue)的大小
使用Java纯手写一个线程池
Das obige ist der detaillierte Inhalt vonSo erstellen Sie einen Java-Thread-Pool. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Leitfaden zur Quadratwurzel in Java. Hier diskutieren wir anhand eines Beispiels und seiner Code-Implementierung, wie Quadratwurzel in Java funktioniert.

Leitfaden zur perfekten Zahl in Java. Hier besprechen wir die Definition, Wie prüft man die perfekte Zahl in Java?, Beispiele mit Code-Implementierung.

Leitfaden zum Zufallszahlengenerator in Java. Hier besprechen wir Funktionen in Java anhand von Beispielen und zwei verschiedene Generatoren anhand ihrer Beispiele.

Leitfaden zur Armstrong-Zahl in Java. Hier besprechen wir eine Einführung in die Armstrong-Zahl in Java zusammen mit einem Teil des Codes.

Leitfaden für Weka in Java. Hier besprechen wir die Einführung, die Verwendung von Weka Java, die Art der Plattform und die Vorteile anhand von Beispielen.

Leitfaden zur Smith-Zahl in Java. Hier besprechen wir die Definition: Wie überprüft man die Smith-Nummer in Java? Beispiel mit Code-Implementierung.

In diesem Artikel haben wir die am häufigsten gestellten Fragen zu Java Spring-Interviews mit ihren detaillierten Antworten zusammengestellt. Damit Sie das Interview knacken können.

Java 8 führt die Stream -API ein und bietet eine leistungsstarke und ausdrucksstarke Möglichkeit, Datensammlungen zu verarbeiten. Eine häufige Frage bei der Verwendung von Stream lautet jedoch: Wie kann man von einem Foreach -Betrieb brechen oder zurückkehren? Herkömmliche Schleifen ermöglichen eine frühzeitige Unterbrechung oder Rückkehr, aber die Stream's foreach -Methode unterstützt diese Methode nicht direkt. In diesem Artikel werden die Gründe erläutert und alternative Methoden zur Implementierung vorzeitiger Beendigung in Strahlverarbeitungssystemen erforscht. Weitere Lektüre: Java Stream API -Verbesserungen Stream foreach verstehen Die Foreach -Methode ist ein Terminalbetrieb, der einen Vorgang für jedes Element im Stream ausführt. Seine Designabsicht ist
