前面虽然提到过很多创建线程的方式,但是在以后的工作中是很少会用到这样不带参数的线程的创建方式,那么为什么要学习这几种线程的创建呢?是因为线程池是基于线程实现的
如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗内存或者“过度切换”命题。
所以线程资源必须通过线程池提供,不允许再应用中自行显示创建线程。
那么什么是线程池?
线程池是一种利用池化技术思想来实现的线程管理技术,主要是为了复用线程、便利地管理线程和任务、并将线程的创建和任务的执行解耦开来。我们可以创建线程池来复用已经创建的线程来降低频繁创建和销毁线程所带来的资源消耗。在JAVA中主要是使用ThreadPoolExecutor类来创建线程池,并且JDK中也提供了Executors工厂类来创建线程池(不推荐使用)。
为什么要使用线程池?
我们可以看出每执行一个任务都需要创建新的线程来执行,创建线程对系统来说开销很高,而且也不知道每个线程的去向。
那么线程池哪有写优点呢?
- 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
- 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
- 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
- 提供更多更强大的功能:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如可以允许任务延期执行或定期执行。
线程池的使用
线程池的创建方法有7钟,但是可以分为两大类
一类是通过Executors实现
一类是通过ThreadPoolExecutors实现
但是目前来说都是通过ThreaPoolExecutors实现,一般不会使用Executors去创建线程池,因为这样的处理方式能让人更明确线程池的运行规则,规避了资源耗尽的风险
线程创建的七种方式:
方式一:创建一个固定大小的线程池,超出的线程会在队列中等待
代码案例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 创建一个固定大小的线程池,超出的线程会在队列中等待
*/
public class ThreadDemo19 {
public static void main(String[] args) {
//创建一个大小为10的线程池
ExecutorService threadpool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 11; i++) {
//执行线程池方法一
// threadpool.submit(()->{
// System.out.println("线程池的名称"+Thread.currentThread().getName());
// });
//执行线程池方法二
// threadpool.submit(new Runnable() {
// @Override
// public void run() {
// System.out.println("线程池的名称"+Thread.currentThread().getName());
// }
// });
//执行线程池方法三
threadpool.execute(()->{
System.out.println("线程池的名称"+Thread.currentThread().getName());
});
}
}
}
执行结果
方式二:创建一个可缓存的线程池
代码案例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 创建一个可缓存的线程池,若线程数超过处理所需,
* 缓存一段时间后会回收,若线程数不够,则新建一个线程
*/
public class ThreadDemo20 {
public static void main(String[] args) {
ExecutorService threadpool = Executors.newCachedThreadPool();
//这里要注意,你有几个任务他就会创建几个线程来执行任务,即便你的电脑是八核,但是还是会创建出5个线程
// 所以这也是使用这种线程池的风险
for (int i = 0; i < 5; i++) {
threadpool.submit(() -> {
System.out.println("线程名称:"+ Thread.currentThread().getName());
});
}
}
}
执行结果
方式三:创建单个线程数的线程池,但是能够保证执行顺序
代码案例
/**
* 创建单个线程的线程池,但是能够保证线程的执行顺序
*/
import java.util.concurrent.ExecutorService;
import java.util.concurrent