计算机系统应用教程网站

网站首页 > 技术文章 正文

使用ExecutorService线程池技术的几点思路及作用

btikc 2024-09-18 08:47:24 技术文章 21 ℃ 0 评论

使用ExecutorService线程池技术的几点思路及作用


一、Java单线程与ExecutorService线程池的对比

在Java线程的构造中,Runnable并不代表线程,只是创建了一个接口,为线程提供方便。Thread才是真正的线程,实现了相关的功能。

在我们的Spring Boot项目中,Spring Boot项目启动就是代表一个主线程,如果在启动过程中报错,则主线程会中断,程序无法运行。如果Spring Boot启动成功之后,新开启的子线程启动报错异常,不会影响主线程运行


1.1Thread的弊端

(1)少了定时、定期、并发控制的逻辑;

(2)新建对象的性能存在问题;

(3)可能不断创建线程,会造成Java程序内存溢出、内存泄漏。



1.2线程池的优点

(1) 能够提供连接池管理线程,避免进度开销,占用开销;

(2)能够提供任务队列管理,当任务队列占用满时,可以拒绝后来的线程;

(3)可以通过队列的形式,逐步取出空闲线程进行任务调度;

(4)当队列中的线程异常时,可以重新创建别的线程进行处理;

(5)能够缓存线程,避免性能影响,对线程池进行管理。



二、线程池的几种用法

2.1newCachedThreadPool

通过无参数,创建无界缓存队列。可以回收超过60秒的空闲线程。当任务超过线程池中的线程数可以创建新线程,线程池的上限可以无限放大,是一种比较常用的线程池管理方法:

示例如下:

ExecutorService testCachedThreadPool = Executors.newCachedThreadPool();

for (int i = 0; i < 10; i++) {

final int undo = i;


testCachedThreadPool .execute(new Runnable() {


@Override

public void run() {

System.out.println(Thread.currentThread().getName()+",undo="+undo);

}

});


try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

运行效果:

newpool-i-thread-i, undo=0

newpool-i-thread-i,undo=1

newpool-i-thread-i,undo=2

newpool-i-thread-i,undo=3

newpool-i-thread-i,undo=4

newpool-i-thread-i,undo=5

newpool-i-thread-i,undo=6

newpool-i-thread-i,undo=7

newpool-i-thread-i,undo=8



2.2newFixedThreadPool

通过创建固定大小的线程池,将超过线程池大小的线程加入LinkedBlockingQueue队列wait加入:

ExecutorService testFixedThreadPool = Executors.newFixedThreadPool(3);

for (int i = 0; i < 10; i++) {

final int undo= i;


testFixedThreadPool .execute(new Runnable() {


@Override

public void run() {

log.info(Thread.currentThread().getName()+",undo="+undo);

}

});


try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

运行效果:

newpool-i-thread-1, undo=0

newpool-i-thread-2,undo=1

newpool-i-thread-3,undo=2

newpool-i-thread-1,undo=3

newpool-i-thread-2,undo=4

newpool-i-thread-3,undo=5

newpool-i-thread-1,undo=6

newpool-i-thread-2,undo=7

newpool-i-thread-3,undo=8



2.3newSingleThreadExecutor

通过创建仅有单个线程的线程池,不需要加入参数,通过唯一的单线程来管理队列,其他的线程都保存在LinkedBlockingQueue中。能过控制线程串行执行:

ExecutorService testSingleThreadExecutor = Executors.newSingleThreadExecutor();

for (int i = 0; i < 5; i++) {

final int undo = i;


testSingleThreadExecutor.execute(new Runnable() {


@Override

public void run() {

System.out.println(Thread.currentThread().getName()+",undo="+undo);

}

});


try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

运行效果,所有任务都等待线程一进行:

newpool-i-thread-1, undo=0

newpool-i-thread-1,undo=1

newpool-i-thread-1,undo=2

newpool-i-thread-1,undo=3

newpool-i-thread-1,undo=4



2.4newScheduledThreadPool

可创建一个定时执行或周期执行任务的线程池,可以指定线程池核心线程个数

ScheduledExecutorService testScheduledThreadPool = Executors.newScheduledThreadPool(5);

//延迟二秒执行定时线程数

testScheduledThreadPool .schedule(new Runnable() {


@Override

public void run() {

System.out.println(Thread.currentThread().getName()+", delay 2s");

}

}, 2, TimeUnit.SECONDS);


//通过周期性地执行任务,延迟5秒后,每3s周期性执行任务

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {


@Override

public void run() {

System.out.println(Thread.currentThread().getName()+", every 5s");

}

}, 5, 3, TimeUnit.SECONDS);

运行效果:

newpool-i-thread-1, delay 2s

newpool-i-thread-1,every 5s

newpool-i-thread-2,every 5s

newpool-i-thread-2,every 5s

newpool-i-thread-3,every 5s

newpool-i-thread-4,every 5s

可以通过延迟执行,为我们创建定时任务调度。



三、线程池应用场景

对比单线程处理,线程池技术节约了资源,便于常态化管理多线程运行。对于提升大家的职业素养是非常有好处的。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表