Java是一门广泛应用于后端开发的高级编程语言。在多线程编程中,线程池被广泛应用以优化性能。线程池通过控制线程数量、管理任务队列等方式来提高程序的响应速度、降低系统负载。
Java中常用的线程池有以下七种:
创建方式
在Java中创建FixedThreadPool线程池时,我们需要使用Executors类提供的静态方法之一。以下是创建一个大小为3的FixedThreadPool线程池的示例代码:
ExecutorService executor = Executors.newFixedThreadPool(3);
用途
FixedThreadPool线程池主要用于处理大量长时间运行的任务,并且需要限制线程数量的情况。线程池创建时就会初始化固定数量的线程,当有任务提交到线程池时,如果有空闲线程就立即执行任务,否则就将任务放入等待队列中,直到有空闲线程再去执行。
优点
缺点
示例代码
下面是一个FixedThreadPool线程池示例,在该示例中,我们创建了一个大小为3的FixedThreadPool线程池,并将5个任务提交到线程池中执行:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FixedThreadPoolDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
final int task = i;
executor.execute(() -> {
System.out.println(String.format("Task %d is executed by thread %d", task, Thread.currentThread().getId()));
});
}
executor.shutdown(); // 关闭线程池
}
}
运行日志讲解
当我们运行上述示例代码时,可以看到如下的运行日志:
Task 0 is executed by thread 13
Task 1 is executed by thread 15
Task 2 is executed by thread 14
Task 3 is executed by thread 13
Task 4 is executed by thread 15
从日志中可以看出,FixedThreadPool线程池在默认情况下使用了3个线程来执行5个任务,当有一个线程完成任务后,会立即去执行队列中等待的任务。
创建方式
在Java中创建CachedThreadPool线程池时,我们需要使用Executors类提供的静态方法之一。以下是创建一个CachedThreadPool线程池的示例代码:
ExecutorService executor = Executors.newCachedThreadPool();
用途
CachedThreadPool线程池主要用于处理大量短时间运行的任务,并且需要快速响应的情况。线程池中的线程数会根据任务数量的多少自动增减,当有任务提交到线程池时,如果有空闲线程就立即执行任务,否则就创建新线程处理任务。
优点
缺点
示例代码
下面是一个CachedThreadPool线程池示例,在该示例中,我们创建了一个CachedThreadPool线程池,并将10个任务提交到线程池中执行:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CachedThreadPoolDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int task = i;
executor.execute(() -> {
System.out.println(String.format("Task %d is executed by thread %d", task, Thread.currentThread().getId()));
});
}
executor.shutdown(); // 关闭线程池
}
}
运行日志讲解
当我们运行上述示例代码时,可以看到如下的运行日志:
Task 0 is executed by thread 20
Task 1 is executed by thread 21
Task 2 is executed by thread 22
Task 3 is executed by thread 23
Task 4 is executed by thread 24
Task 6 is executed by thread 26
Task 8 is executed by thread 27
Task 7 is executed by thread 25
Task 9 is executed by thread 21
Task 5 is executed by thread 20
从日志中可以看出,CachedThreadPool线程池中的线程数量随着任务的多寡进行自动调整,能够较快地响应请求。在任务结束后,空闲线程会被保留一段时间,以便处理下一次的任务请求。
创建方式
在Java中创建ScheduledThreadPool线程池时,我们需要使用Executors类提供的静态方法之一。以下是创建一个大小为3的ScheduledThreadPool线程池的示例代码:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
用途
ScheduledThreadPool线程池主要用于需要延迟执行或周期性执行任务的情况。可以使用该线程池在固定时间后执行任务、定期执行任务或者在上一个任务完成后再执行下一个任务。
优点
缺点
示例代码
下面是一个ScheduledThreadPool线程池示例,在该示例中,我们创建了一个大小为2的ScheduledThreadPool线程池,并且分别设定了延迟1秒后执行任务和每隔2秒执行一次任务的定时器:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolDemo {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
executor.schedule(() -> {
System.out.println("Task 1 is executed after 1 second delay");
}, 1, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(() -> {
System.out.println("Task 2 is executed every 2 seconds");
}, 0, 2, TimeUnit.SECONDS);
}
}
运行日志讲解
当我们运行上述示例代码时,可以看到如下的运行日志:
Task 1 is executed after 1 second delay
Task 2 is executed every 2 seconds
Task 2 is executed every 2 seconds
Task 2 is executed every 2 seconds
Task 2 is executed every 2 seconds
Task 1 is executed after 1 second delay
Task 2 is executed every 2 seconds
Task 2 is executed every 2 seconds
Task 2 is executed every 2 seconds
Task 2 is executed every 2 seconds
从日志中可以看出,ScheduledThreadPool线程池中的两个线程分别用来执行两个定时器中的任务。第一个定时器会延迟1秒后执行任务,而第二个定时器则是每隔2秒执行一次任务。在任务结束后,线程仍然被保留以供下一次任务使用。
创建方式
在Java中创建SingleThreadExecutor线程池时,我们需要使用Executors类提供的静态方法之一。以下是创建一个SingleThreadExecutor线程池的示例代码:
ExecutorService executor = Executors.newSingleThreadExecutor();
用途
SingleThreadExecutor线程池主要用于需要按照顺序执行任务的情况。它保证所有的任务都由同一个线程依次执行,避免了多线程操作带来的竞争和锁的问题。
优点
缺点
示例代码
下面是一个SingleThreadExecutor线程池示例,在该示例中,我们创建了一个SingleThreadExecutor线程池,并将10个任务提交到线程池中执行:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SingleThreadExecutorDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int task = i;
executor.execute(() -> {
System.out.println(String.format("Task %d is executed by thread %d", task, Thread.currentThread().getId()));
});
}
executor.shutdown(); // 关闭线程池
}
}
运行日志讲解
当我们运行上述示例代码时,可以看到如下的运行日志:
Task 0 is executed by thread 20
Task 1 is executed by thread 20
Task 2 is executed by thread 20
Task 3 is executed by thread 20
Task 4 is executed by thread 20
Task 5 is executed by thread 20
Task 6 is executed by thread 20
Task 7 is executed by thread 20
Task 8 is executed by thread 20
Task 9 is executed by thread 20
从日志中可以看出,SingleThreadExecutor线程池中只有一个线程用来执行任务,并且所有任务都由同一个线程依次执行。
创建方式
在Java中创建WorkStealingPool线程池时,我们需要使用Executors类提供的静态方法之一。以下是创建一个WorkStealingPool线程池的示例代码:
ExecutorService executor = Executors.newWorkStealingPool();
用途
WorkStealingPool线程池主要用于处理大量独立任务的情况。该线程池会自动将任务分配给空闲的线程执行,同时可以根据需要增加或减少线程数以适应当前的工作负载。
优点
缺点
示例代码
下面是一个WorkStealingPool线程池示例,在该示例中,我们创建了一个WorkStealingPool线程池,并将10个任务提交到线程池中执行:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class WorkStealingPoolDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newWorkStealingPool();
for (int i = 0; i < 10; i++) {
final int task = i;
executor.execute(() -> {
System.out.println(String.format("Task %d is executed by thread %d", task, Thread.currentThread().getId()));
});
}
executor.shutdown(); // 关闭线程池
}
}
运行日志讲解
当我们运行上述示例代码时,可以看到如下的运行日志:
Task 7 is executed by thread 14
Task 4 is executed by thread 14
Task 8 is executed by thread 12
Task 1 is executed by thread 15
Task 9 is executed by thread 12
Task 6 is executed by thread 15
Task 3 is executed by thread 12
Task 2 is executed by thread 13
Task 5 is executed by thread 13
Task 0 is executed by thread 14
从日志中可以看出,WorkStealingPool线程池会自动将任务分配给空闲的线程执行,并且每次执行的顺序是不确定的。
创建方式
在Java中创建ForkJoinPool线程池时,我们需要使用ForkJoinPool类提供的构造方法之一。以下是创建一个ForkJoinPool线程池的示例代码:
ForkJoinPool forkJoinPool = new ForkJoinPool();
用途
ForkJoinPool线程池主要用于处理大量并行任务的情况。它使用分治算法将任务拆分成多个小任务,同时利用工作窃取(work-stealing)算法提高CPU利用率。
优点
缺点
示例代码
下面是一个ForkJoinPool线程池示例,在该示例中,我们创建了一个ForkJoinPool线程池,并使用分治算法将任务拆分成多个小任务。最终,所有任务都将由线程池中的线程执行:
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class ForkJoinPoolDemo {
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.invoke(new MyTask(0, 10));
forkJoinPool.shutdown(); // 关闭线程池
}
}
class MyTask extends RecursiveAction {
private int start;
private int end;
public MyTask(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected void compute() {
if (end - start < 2) { // 如果任务量小于2,直接执行任务
System.out.println(String.format("Task %d is executed by thread %d", start, Thread.currentThread().getId()));
return;
}
// 否则将任务拆分成两个子任务,交给其他线程执行
int middle = (start + end) / 2;
MyTask left = new MyTask(start, middle);
MyTask right = new MyTask(middle, end);
left.fork();
right.fork();
}
}
运行日志讲解
当我们运行上述示例代码时,可以看到如下的运行日志:
Task 0 is executed by thread 14
Task 9 is executed by thread 13
Task 8 is executed by thread 14
Task 7 is executed by thread 13
Task 6 is executed by thread 14
Task 5 is executed by thread 13
Task 4 is executed by thread 13
Task 3 is executed by thread 14
Task 2 is executed by thread 13
Task 1 is executed by thread 14
从日志中可以看出,ForkJoinPool线程池使用分治算法将任务拆分成两个子任务,其中一些子任务可能会由其他线程执行。最终,所有任务都将由线程池中的线程执行。
创建方式
在Java中创建SingleThreadScheduledExecutor线程池时,我们需要使用Executors类提供的newSingleThreadScheduledExecutor()方法。以下是创建一个SingleThreadScheduledExecutor线程池的示例代码:
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
用途
SingleThreadScheduledExecutor线程池主要用于需要定期执行任务的情况。它会按照指定的时间间隔重复执行任务,且所有任务都由单个线程顺序执行。
优点
缺点
示例代码
下面是一个SingleThreadScheduledExecutor线程池示例,在该示例中,我们创建了一个SingleThreadScheduledExecutor线程池,并提交多个定时任务。所有任务都将由单个线程顺序执行:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class SingleThreadScheduledExecutorDemo {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("Task 1 is executed by thread " + Thread.currentThread().getId());
}
}, 0, 1, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("Task 2 is executed by thread " + Thread.currentThread().getId());
}
}, 0, 2, TimeUnit.SECONDS);
executor.shutdown(); // 关闭线程池
}
}
运行日志讲解
当我们运行上述示例代码时,可以看到如下的运行日志:
Task 1 is executed by thread 17
Task 2 is executed by thread 17
Task 1 is executed by thread 17
Task 1 is executed by thread 17
Task 2 is executed by thread 17
Task 1 is executed by thread 17
Task 1 is executed by thread 17
Task 2 is executed by thread 17
Task 1 is executed by thread 17
...
从日志中可以看出,SingleThreadScheduledExecutor线程池按照指定的时间间隔重复执行任务,并且所有任务都由单个线程顺序执行。
想了解ThreadPoolExecutor的更多东西,请点击本人的另一篇文章:
Java多线程:玩转ThreadPoolExecutor线程池必须知道这几点
页面更新:2024-02-19
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号