我们使用线程的时候就去创建一个线程,这样实现起来非常便捷,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就大大降低了系统的效率,因为频繁创建线程和销毁线程需要时间。
那么有没有一种方法使得线程能够复用呢?就是执行完一个任务并不立即被销毁,而继续执行下一个任务。在JDK1.5之后java提供了一个对线程池的操作来解决这个问题。
线程池:就是存储线程的容器(集合),其中的线程可以反复使用。
简单实现原理
线程池的优点:
- 降低系统资源消耗;
- 提高系统响应速度;
- 方便管理线程。
java.util.concurrent.Executors:线程池的工厂类,用来生产线程池。
创建线程池对象:利用静态方法newFixedThreadPool(int nThreads);
参数:int nThreads:线程池的线程数量;
返回值:新建的线程池,返回的是ExecutorService接口的实现类对象。
java.util.concurrent.ExecutorService:线程池的接口,用来从线程池中获取线程,并调用start方法执行线程任务。
submit(Runnable task)提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功完成时将会返回给定的结果。
销毁线程池:void shutdown();
线程池的使用步骤:
- 使用线程池的工程类提供的静态方法newFixedThreadPool(int nThreads)来生产一个指定线程数量的线程池;
- 创建一个实现了Runnable接口的类,重写run方法,设置线程任务;
- 调用ExecutorService接口中的submit方法,传递线程对象,开启线程,执行run方法;
- 调用ExecutorService接口中的shutdown方法,销毁线程池。
下面用代码来简单实现线程池操作
Runnable接口的实现类,重写run方法
package com.etime;
public class RunnableImpl implements Runnable{
@Override
public void run() {
System.out.println("执行了一个新的线程"+Thread.currentThread().getName());
}
}
主函数main
package com.etime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test01 {
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(2);
RunnableImpl runnable=new RunnableImpl();
es.submit(runnable);//执行了一个新的线程pool-1-thread-2
es.submit(runnable);//执行了一个新的线程pool-1-thread-1
es.submit(runnable);//执行了一个新的线程pool-1-thread-2
es.shutdown();
}
}
运行结果
线程池创建了两个线程,由于有三个任务,所以第三个任务是第一个任务完成之后的线程来执行的。