线程池
重复创建线程非常浪费系统资源,为了解决这个问题,Java中提供了线程池。
线程池:是一个可以容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,节省了资源。
为什么要使用线程池?
在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,创建和销毁线程花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务。
线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。
创建线程池
方式1.使用Runnable接口
线程池通过线程池工厂创建,再调用线程池的方法获取线程,再通过线程去执行任务。
使用工厂类Executors
中的静态方法创建线程池对象,指定线程个数。
static ExecutorService newFixedThreadPool(int n)
方法返回线程池对象ExecutorService接口的实现类。实现类调用方法submit(Runnable r)提交线程执行任务。关闭线程池方法shutdown(),但一般不用。
使用线程池中线程对象的步骤:
- 创建线程池对象
- 创建Runnable接口子类对象
- 提交Runnable接口子类对象
- 关闭线程池
public class ThreadPoolDemo {
public static void main(String[] args) {
// 调用工厂类的静态方法,创建线程池对象
// 返回线程池对象,返回的是接口
ExecutorService es = Executors.newFixedThreadPool(2);
// 调用接口实现类对象es中的方法submit提交线程任务(Runnable接口实现类)
// 传递Runnable接口的实现类对象
es.submit(new ThreadPoolRunnable());
es.submit(new ThreadPoolRunnable());
es.submit(new ThreadPoolRunnable());
// es.shutdown(); 一般不用
}
}
public class ThreadPoolRunnable implements Runnable{
public void run() {
System.out.println(Thread.currentThread().getName() + " 线程提交任务");
}
}
方法2.使用Callable接口
Callable接口和Runnable接口的功能类似,其中的call()与run()方法类似,但有返回值并且可以抛出异常,比run()方法更灵活。
上面提到的ExecutorService类的实现类的submit()方法有返回值,返回值是Feature<>接口的实现类。Feature<>的实现类的get()方法可以获得call()方法的返回值,其中的泛型就是返回值的类型。
使用线程池中线程对象的步骤:
- 创建线程池对象
- 创建Callable接口子类对象
- 提交Callable接口子类对象
- 关闭线程池
/*
* 实现线程程序的第三个方式,实现Callable接口方式
* 实现步骤
* 工厂类Executors静态方法newFixedThreedPool方法创建线程池对象
* 线程池对象ExecutorService接口实现类,调用方法submit提交线程任务
* submit(Callable c)
*/
public class ThreadPoolDemo1 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService es = Executors.newFixedThreadPool(2);
// 提交线程任务的方法submit方法返回Future接口的实现类
Future<String> f = es.submit(new ThreadPoolCallable());
String s = f.get();
System.out.println(s);
}
}
/*
* Callable接口的实现类,作为线程提交任务出现
* 使用方法返回值
*/
public class ThreadPoolCallable implements Callable<String>{
public String call() {
return "abc";
}
}