前一篇介绍了Java多线程的创建方式,其中有一种就是通过线程池来启动,这一篇我们一起来聊聊线程池。
先说说什么是线程池:Java提供了一个线程队列,队列中保存着所有等待状态的线程,避免了创建与销毁额外的开销,提高了程序响应速度。
线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法。每个 ThreadPoolExecutor 还维护着一些基本的统计数据,如完成的任务数。
线程池的体系结构如下:
java.util.concurrent.Executor : 负责线程的使用与调度的根接口
|--ExecutorService 子接口: 线程池的主要接口
|--ThreadPoolExecutor 线程池的实现类
|--ScheduledExecutorService 子接口:负责线程的调度
|--ScheduledThreadPoolExecutor :继承 ThreadPoolExecutor, 实现 ScheduledExecutorService
JavaApi推荐大家直接使用 Executors 这个工具类,里面封装了很多方便的工具方法,下面就通过它来讲解创建线程的具体方式:
第一种:
-
Executors.newCachedThreadPool()
(自动缓存无界线程池),根据需要创建新的线程,在可用时将重用先前构建的线程,如果没有空闲的线程,将创建一个新的线程,并添加到池中,池中默认超过六十秒空闲的线程被终止并从缓存中移除。
public class TestCachedThreadPool {
public static void main(String[] args) {
try{
ExecutorService pool = Executors.newCachedThreadPool();
for (int i=0;i<5;i++){
pool.submit(new TestThread());
}
pool.shutdown();
}catch (Exception e){
e.printStackTrace();
}
}
}
class TestThread implements Runnable{
@Override
public void run() {
System.out.println("当前线程名称:"+Thread.currentThread().getName());
}
}
循环5次,创建5个线程,可以看到执行结果如下,每次都是新启的线程:
循环为10次,结果如下:
第二种:
-
Executors.newFixedThreadPool(int)
(固定大小的线程池),顾名思义即可以创建具体大小的线程池,在创建时指定池大小
public class TestThreadPoolTwo {
public static void main(String[] args) {
try {
//1. 创建线程池
ExecutorService pool = Executors.newFixedThreadPool(3);
ThreadPoolDemoTwo tpd = new ThreadPoolDemoTwo();
//2. 为线程池中的线程分配任务
for (int i = 0; i < 5; i++) {
pool.submit(tpd);
}
//3. 关闭线程池
pool.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ThreadPoolDemoTwo implements Runnable {
@Override
public void run() {
System.out.println("当前线程名字:" + Thread.currentThread().getName());
}
}
执行结果如下,只会创建3个线程,循环调用:
第三种:
-
Executors.newSingleThreadExecutor()
(单个后台线程),即该种方法只会创建一个线程public class TestSingleThreadPool { public static void main(String[] args) { try{ ExecutorService pool = Executors.newSingleThreadExecutor(); for (int i=0;i<10;i++){ pool.submit(new TestThread()); } pool.shutdown(); }catch (Exception e){ e.printStackTrace(); } } } class TestThread implements Runnable{ @Override public void run() { System.out.println("当前线程名称:"+Thread.currentThread().getName()); } }
执行结果如下,循环调用池中线程处理业务:
第四种:
-
Executors.newScheduledThreadPool(调度线程池),该种方法可以创建固定大小并可以设置延迟执行的线程池
public class TestScheduledThreadPool { static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws Exception { ScheduledExecutorService pool = Executors.newScheduledThreadPool(3); for (int i = 0; i < 5; i++) { Future<Integer> result = pool.schedule(new Callable<Integer>(){ @Override public Integer call() throws Exception { int num = new Random().nextInt(100);//生成随机数 System.out.println("当前时间:"+sdf.format(new Date())+"当前线程名称:"+Thread.currentThread().getName() + "随机数 : " + num); return num; } }, 1, TimeUnit.SECONDS); System.out.println("计算的结果:"+result.get()); } pool.shutdown();//关闭线程池 } }
执行结果:
以上就是Executors工具类提供的常用创建线程池方法,希望能帮助到学习Java多线程的小伙伴。
欢迎各们小伙伴加群交流,期待你们的加入,群号:1077176637