线程池:顾名思义就是一个装了许多线程的池子
主要用来创建和管理线程对象的容器(达到线程复用的效果)
好处:
1.减少资源的消耗,避免频繁的创建和销毁线程
2.提高程序的响应速度
3.提高线程的可管理性
创建线程池对象,需要使用Executors工具类的方法
public static ExecutorService newFixedThreadPool(int nThreads) 创建一个线程池对象,并规定池中包含nThreads个线程
ExecutorService es = Executors.newFixedThreadPool(5);
ExecutorService为线程池对象;参数 5 为线程的数量
线程池ExecutorService对象常用方法:
Future <?> submit (Runnable task) 提交一个可运行的任务执行,并返回一个表示该任务Future对象
ExecutorService es = Executors.newFixedThreadPool(5);
Future<?> f = es.submit(new Runnable() { //返回一个Future<?>对象
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
});
System.out.println(f);
Future <T> submit (Callable<T> task) 提交值返回任务以执行,并返回代表任务待处理结果的Future
ExecutorService es = Executors.newFixedThreadPool(5);
Future<Integer> f = es.submit(new Callable<Integer>() { //返回一个Future<T>对象
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
return sum;
}
});
void shutdown() 销毁线程池
ExecutorService es = Executors.newFixedThreadPool(5);
es.shutdown();
使用完线程池后都应调用该方法销毁
线程池提交Runnable任务:
1.创建线程对象并制定线程数量
ExecutorService es = Executors.newFixedThreadPool(5);
2.创建实现Runnable接口的实现类,并重写Run方法
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
}
3.创建实现类对象,调用线程池submit()方法传递实现类对象
ExecutorService es = Executors.newFixedThreadPool(5);
es.submit(new MyRunnable());
4.销毁线程池
这样就完成了,从线程池中获取线程并执行Runnable任务
线程池提交Callable任务:
1.创建线程池并指定线程数量
ExecutorService es = Executors.newFixedThreadPool(5);
2.创建类实现Callable接口和重写call()方法
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
return sum;
}
}
3.创建实现类对象,调用线程池的submit()方法,将实现类对象传入
ExecutorService es = Executors.newFixedThreadPool(5);
es.submit(new MyCallable());
4.销毁线程池
Future接口中有一个get()方法,可以获取Callable接口中,call方法的返回值
ExecutorService es = Executors.newFixedThreadPool(5);
Future<Integer> f = es.submit(new MyCallable());
System.out.println(f.get()); //输出:45
get还有阻塞的作用,会阻塞当前线程的执行
因为获取返回值一定要等待方法运行完才会有返回值
所以其他线程只能等该线程执行完或者使用线程池的其他线程
Callable和Runnable两种任务选择:
1.若执行任务完后,需要得到一个返回值,则使用Callable
2.若不需要返回值,则使用两种方法都可以