创建一个具有固定线程数的线程池,当创建的线程达到最大数量后,就不再创建新的线程。当所有的线程都在使用时,新提交的任务会阻塞在队列中,直至有线程空闲出来。
package com.dfire.monitor.service.impl.poolTest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author : baigp
* create at: 2020/7/22 15:49
* @description:
*/
public class FixedThreadPoolTest {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Runnable run = new Runnable() {
@Override
public void run() {
try {
System.out.println("当前线程名称:" + Thread.currentThread().getName() + " , 当前时间为:" + sdf.format(new Date()));
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ExecutorService executorService = Executors.newFixedThreadPool(2);
for (int i = 0 ; i < 10 ; i++){
executorService.execute(run);
}
}
}
打印结果:
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:23
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:23
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:26
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:26
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:29
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:29
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:32
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:32
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:14:35
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:14:35
从打印结果可以看出,一共创建了2个线程,和代码汇总配置的线程数相对应。第三、四个任务提交时,由于两个线程被占用着,所以阻塞在队列中,直至第一、二个任务休眠三秒后,释放了线程,第三、四个任务才开始执行。
package com.dfire.monitor.service.impl.poolTest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author : baigp
* create at: 2020/7/22 16:03
* @description:
*/
public class SingleThreadExecutorTest {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Runnable run = new Runnable() {
@Override
public void run() {
try {
System.out.println("当前线程名称:" + Thread.currentThread().getName() + " , 当前时间为:" + sdf.format(new Date()));
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ExecutorService executroService = Executors.newSingleThreadExecutor();
for (int i = 0 ; i < 10; i++){
executroService.execute(run);
}
}
}
打印结果:
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:19
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:22
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:25
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:28
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:31
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:34
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:37
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:40
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:43
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 16:26:46
可以看出,自始至终只创建了一个线程,后面的任务等待前面的任务执行完毕后才开始执行。
可缓冲线程池。特点:灵活。 没有线程最大数量的限制,当一个任务被提交到线程池时,如果有闲置的线程,则选取一个闲置线程执行,如果没有闲置线程,则创建一个新线程。 对于线程池中的线程,闲置60s后会自动销毁以节省资源。
package com.dfire.monitor.service.impl.poolTest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author : baigp
* create at: 2020/7/22 16:30
* @description:
*/
public class CachedThreadPoolTest {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Runnable run = new Runnable() {
@Override
public void run() {
try {
System.out.println("当前线程名称:" + Thread.currentThread().getName() + " , 当前时间为:" + sdf.format(new Date()));
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0 ; i < 1000 ; i++){
executorService.execute(run);
}
}
}
打印结果:
当前线程名称:pool-1-thread-5 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-6 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-4 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-2 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-8 , 当前时间为:2020-07-22 16:32:21
省略中间的打印内容...
当前线程名称:pool-1-thread-997 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-998 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-999 , 当前时间为:2020-07-22 16:32:21
当前线程名称:pool-1-thread-1000 , 当前时间为:2020-07-22 16:32:21
可以看出,一共创建了1000个线程。
固定线程数上限的线程池,并支持定时和周期性执行任务。
package com.dfire.monitor.service.impl.poolTest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
/**
* @author : baigp
* create at: 2020/7/22 17:11
* @description:
*/
public class ScheduledThreadPoolTest {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Runnable run = new Runnable() {
@Override
public void run() {
try {
System.out.println("当前线程名称:" + Thread.currentThread().getName() + " , 当前时间为:" + sdf.format(new Date()));
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
System.out.println("开始执行时间:" + sdf.format(new Date()));
executorService.scheduleAtFixedRate(run , 3, 5 , TimeUnit.SECONDS);
}
}
打印结果:
开始执行时间:2020-07-22 17:17:57
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:18:00
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:18:05
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:18:10
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:18:15
。。。
可以看出,executorService 添加线程任务后,首先延迟3s,然后执行run(),而后按照5s/次的频率定时执行run()方法。
注意:如果执行频率由5s/次加快到2s/次,run()方法执行一次需要3s(休眠3s),那么后面的任务会阻塞,等前面的任务执行完后再执行,所用的线程自始至终都是同一个。
执行频率由5s/次加快到2s/次后的打印结果:
开始执行时间:2020-07-22 17:22:47
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:22:50
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:22:53
当前线程名称:pool-1-thread-1 , 当前时间为:2020-07-22 17:22:56
。。。