När vi utvecklar en flertrådad applikation måste vi vanligtvis hantera att organisera arbetet med trådar. Ju större vår applikation och ju fler trådar vi behöver för flertrådade uppgifter, desto flerKörbarobjekt vi skapar.

Det bör noteras här att skapa en tråd i Java är en ganska dyr operation. Om vi ​​skapar en ny instans av tråden varje gång för att utföra en operation kommer vi att få stora problem med prestanda och, som ett resultat, med applikationens hälsa.

Här kommer en trådpool och ThreadPoolExecutor till vår hjälp.

En trådpool är en uppsättning förinitierade trådar. Dess storlek kan vara fast eller variabel.

Om det finns fler uppgifter än trådar, väntar uppgifter i en uppgiftskö. Den N:e tråden i poolen tar en uppgift från kön, och efter att den är klar, plockar tråden upp en ny uppgift från kön. När alla uppgifter i kön är utförda förblir trådarna aktiva och väntar på nya uppgifter. När nya uppgifter dyker upp börjar trådarna också köra dem.

ThreadPoolExecutor

Från och med Java 5 fick Executor-ramverket en multithreading-lösning. I allmänhet har den massor av komponenter och dess syfte är att hjälpa oss att effektivt hantera köer och trådpooler.

De huvudsakliga gränssnitten är Executor och ExecutorService .

Executor är ett gränssnitt med en enda void execute (körbar körbar) metod.

När du skickar en uppgift till en implementering av denna metod, vet att den kommer att köras asynkront i framtiden.

ExecutorService — Ett gränssnitt som utökar Executor- gränssnittet och lägger till möjligheter för att utföra uppgifter. Den har också metoder för att avbryta en pågående uppgift och avsluta trådpoolen.

ThreadPoolExecutor implementerar Executor- och ExecutorService- gränssnitten och separerar uppgiftsskapande från aktivitetsexekvering. Vi måste implementera körbara objekt och skicka dem till en exekutor. ThreadPoolExecutoransvarar sedan för att utföra uppgifterna och skapa och arbeta med trådar .

Efter att en uppgift har skickats för exekvering används en befintlig tråd i poolen. Detta förbättrar prestandan. Det löser problemet med att slösa resurser på att skapa och initiera en ny tråd, och sedan igen på sophämtning när vi är klara med tråden.

ThreadPoolExecutor har 4 konstruktörer:


ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime, 
TimeUnit unit, 
BlockingQueue<Runnable> workQueue)
    

ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
    

ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime, 
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
    

ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime, 
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory, 
RejectedExecutionHandler handler)
    

ThreadPoolExecutor - konstruktorn har följande parametrar:

corePoolSize Denna parameter indikerar hur många trådar som kommer att vara klara (startade) när executor-tjänsten startar.
maximumPoolSize Det maximala antalet trådar som en exekutortjänst kan skapa.
keepAliveTime Tiden som en frigjord tråd kommer att fortsätta leva innan den förstörs om antalet trådar är större äncorePoolSize. Tidsenheterna anges i nästa parameter.
enhet Tidsenheter (timmar, minuter, sekunder, millisekunder, etc.).
arbetskö Implementering av kö för uppgifter.
hanterare Hanterare för uppgifter som inte kan slutföras.
threadFactory Ett objekt som skapar nya trådar på begäran. Att använda trådfabriker gör anrop till en ny trådhårdvaruoberoende, vilket gör att applikationer kan använda speciella trådunderklasser, prioriteringar och så vidare.

Skapa en ThreadPoolExecutor

Verktygsklassen Executors kan förenkla skapandet av en ThreadPoolExecutor . Metoderna i den här verktygsklassen hjälper oss att förbereda enThreadPoolExecutorobjekt.

newFixedThreadPool — Skapar en trådpool som återanvänder ett fast antal trådar för att utföra valfritt antal uppgifter.

ExecutorService executor = Executors.newFixedThreadPool(10);
                    
newWorkStealingPool — Skapar en trådpool där antalet trådar är lika med antalet tillgängliga processorkärnor för JVM. Standardnivån för samtidighet är ett. Detta innebär att lika många trådar kommer att skapas i poolen som det finns CPU-kärnor tillgängliga för JVM. Om samtidighetsnivån är 4 används det godkända värdet istället för antalet kärnor.

ExecutorService executor = Executors.newWorkStealingPool(4);
                    
newSingleThreadExecutor — Skapar en pool med en enda tråd för att utföra alla uppgifter.

ExecutorService executor = Executors.newSingleThreadExecutor();
                    
newCachedThreadPool — Skapar en trådpool som skapar nya trådar efter behov, men återanvänder tidigare skapade trådar när de är tillgängliga.

ExecutorService executor = Executors.newCachedThreadPool();
                    
newScheduledThreadPool — Skapar en trådpool som kan schemalägga kommandon att utföras efter en viss fördröjning eller periodiskt.

ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
                    

Vi kommer att överväga varje typ av pool i följande lektioner.