• 周六. 10 月 12th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

Java Concurrent Programming: the use of Java’s four thread pools and the custom thread factory

King Wang

1 月 3, 2022

List of articles

    • introduction
    • There are four thread pools
      • newCachedThreadPool: Cacheable thread pool
      • newFixedThreadPool: Fixed-length thread pool
      • newSingleThreadExecutor: Single-threaded thread pool
      • newScheduledThreadPool: Support timed fixed-length thread pools
    • Customize ThreadFactory

introduction

Through the previous article , We learned Executor Core classes in the framework ThreadPoolExecutor , We have some understanding of the core scheduling mechanism of thread pool , And use it successfully ThreadPoolExecutor A thread pool is created .

And in the Java in , except ThreadPoolExecutor ,Executor Four thread pools are also provided in the framework , All four of these thread pools are configured either directly or indirectly ThreadPoolExecutor The parameter of , about ThreadPoolExecutor Class for unfamiliar readers Java Concurrent programming :Java Thread pool core ThreadPoolExecutor Use and principle analysis

There are four thread pools

The four thread pools are :newCachedThreadPool、newFixedThreadPool 、newScheduledThreadPool and newSingleThreadExecutor , The following sections describe each of these thread pools .

newCachedThreadPool: Cacheable thread pool

Source code :

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

newCachedThreadPool Is to return one ThreadPoolExecutor example , You can see the characteristics of this thread pool from the source code :

1、 The number of core threads in the thread pool is 0, The maximum number of threads can be reached Integer Type maximum ;

2、 establish ThreadPoolExecutor The parameter passed in the instance is one SynchronousQueue example , When creating a task , If there are idle threads, reuse them , If not, create a new thread .

3、 Threads are idle over 60s Words , Will be destroyed .

usage :

public static void main(String[] args) {
// Definition ExecutorService example
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// call execute Method
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread() + ":" + index);
}
});
}
}

The code above because each loop is executed every second , This is enough time for previous threads to finish working , And reuse the thread in the new loop , The program runs as follows :

Thread[pool-1-thread-1,5,main]:0
Thread[pool-1-thread-1,5,main]:1
Thread[pool-1-thread-1,5,main]:2
Thread[pool-1-thread-1,5,main]:3
Thread[pool-1-thread-1,5,main]:4
Thread[pool-1-thread-1,5,main]:5
Thread[pool-1-thread-1,5,main]:6
Thread[pool-1-thread-1,5,main]:7
Thread[pool-1-thread-1,5,main]:8
Thread[pool-1-thread-1,5,main]:9

newFixedThreadPool: Fixed-length thread pool

Source code :

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

Thread pool features :

1、 The maximum number of threads in the thread pool is equal to the number of core threads , And thread pool threads are not destroyed for idle timeouts .

2、 The queue used is LinkedBlockingQueue, Indicates if the current thread count is less than the number of core threads , Then even if there are idle threads, they will not reuse threads to perform tasks , Instead, create a new thread to execute the task . If the number of tasks currently executing is greater than the number of core threads , At this point, the resubmit task is waiting in the queue , Until there are threads available .

usage :

public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread() + ":" + index);
}
});
}
}

Define a number of threads as 3 Thread pool of , loop 10 Execution times , You can see that there are always only three threads running , give the result as follows :

Thread[pool-1-thread-1,5,main]:0
Thread[pool-1-thread-2,5,main]:1
Thread[pool-1-thread-3,5,main]:2
Thread[pool-1-thread-1,5,main]:3
Thread[pool-1-thread-2,5,main]:4
Thread[pool-1-thread-3,5,main]:5
Thread[pool-1-thread-1,5,main]:6
Thread[pool-1-thread-2,5,main]:7
Thread[pool-1-thread-3,5,main]:8
Thread[pool-1-thread-1,5,main]:9

newSingleThreadExecutor: Single-threaded thread pool

Source code :

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

You can see it from the source code , The thread pool is basically one thread newFixedThreadPool, It has only one thread working , All tasks are executed in the specified order .

usage :

and newFixedThreadPool similar , Only one thread is working all the time , I’m not going to post the code here .

newScheduledThreadPool: Support timed fixed-length thread pools

Source code :

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}

newScheduledThreadPool The method does not return one directly ThreadPoolExecutor example , But by having a timing function ThreadPoolExecutor, That is to say ScheduledThreadPoolExecutor Come back to ThreadPoolExecutor example , You can see it in the source code :

1、 This thread pool can set the number of core threads , Maximum number of threads and newCachedThreadPool equally , All are Integer.MAX_VALUE.

2、 The queue for this thread pool is DelayedWorkQueue, It has the function of delay and timing .

usage :

public static void main(String[] args) {
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
// Delay 3 Seconds to perform , Only once
((ScheduledExecutorService) scheduledThreadPool).schedule(new Runnable() {
@Override
public void run() {
System.out.println(" Delay ========");
}
},3,TimeUnit.SECONDS);
// Delay 1 Execute every two seconds after the second
((ScheduledExecutorService) scheduledThreadPool).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(" perform ============");
}
},1,2,TimeUnit.SECONDS); // The unit is seconds
}

Customize ThreadFactory

So much for the use of the four thread pools , It’s worth noting that , In addition to the above parameters ,Executors Class also provides passable access to these four thread pools ThreadFactory Overload method of , The following is their source code :

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}

ThreadFactory Is an interface class , This is often referred to as a thread factory , There is only one way , Can be used to create threads :

Thread newThread(Runnable r);

By default ,ThreadPoolExecutor Passed in by the constructor ThreadFactory Parameter is Executors Class defaultThreadFactory(), Equivalent to a thread factory , Helped us create the required threads in the thread pool .

besides , We can also customize it ThreadFactory, And according to their own needs to manipulate the thread , Here is the example code :

public static void main(String[] args) {
ExecutorService service = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
System.out.println(" I am a thread " + r);
return t;
}
}
);
// use lambda The expression writes the logic in the body of the method
Runnable run = () -> {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " Being implemented ");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
for (int i = 0; i < 5; i++) {
service.submit(run);
}
// Make sure you close it here
service.shutdown();
}

After running the code , The control row outputs five rows “ I am a thread java.util.concurrent.ThreadPoolExecutor…..” Information about , It also proves our custom ThreadFactory Made a difference .

发表回复