java执行器与线程池
构建一个新的线程是有一定代价的。如果程序需要创建大量生命周期很短的线程,应该使用线程池。
执行器Executor
执行器类有许多静态工厂方法构建线程池。
方法 | 描述 |
---|---|
newCachedThreadPool | 必要时创建新线程;空闲线程会被保留60秒 |
newFixedThreadPool | 该池包含固定数量的线程;空闲线程会一直被保留 |
newSingleThreadExecutor | 只有一个线程的“池”,该线程顺序执行每一个提交的任务 |
newScheduledThreadPool | 用于预定执行而构建的固定线程池,替代java.util.Timer |
newSingleThreadScheduledExecutor | 用于预定执行而构建的单线程池 |
线程池
上述表中前三个方法返回实现了ExecutorService接口的ThreadPoolExecutor对象。
使用submit()方法提交Runnable对象或Callable对象。
当用完一个线程池的时候,调用shutdown()。
例子,使用线程池查询文件
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class SearchFile {
public static void main(String[] args) throws ExecutionException, InterruptedException {
File directory = new File("D:\\");
String filename = "确认.pdf";
ExecutorService pool = Executors.newCachedThreadPool();
SearchFileThread search = new SearchFileThread(directory, filename, pool);
Future<List<String>> futures = pool.submit(search);
List<String> results = futures.get();
for (String str :
results) {
System.out.println(str);
}
pool.shutdown();
int largestPoolSize = ((ThreadPoolExecutor)pool).getLargestPoolSize();
System.out.println("线程池最大的长度:" + largestPoolSize);
}
static class SearchFileThread implements Callable<List<String>> {
private File directory;
private String filename;
private ExecutorService pool;
public SearchFileThread(File directory, String filename, ExecutorService pool) {
this.directory = directory;
this.filename = filename;
this.pool = pool;
}
@Override
public List<String> call() throws Exception {
List<String> resultList = new ArrayList<>();
File[] files = directory.listFiles();
List<Future<List<String>>> results = new ArrayList<>();
if (files != null) {
for (File file :
files) {
if (file.isDirectory()) {
SearchFileThread thread = new SearchFileThread(file, filename, pool);
Future<List<String>> result = pool.submit(thread);
results.add(result);
} else {
// System.out.println(file.getAbsolutePath());
if (file.getName().equals(filename)) {
resultList.add(file.getAbsolutePath());
}
}
}
}
for (Future<List<String>> future :
results) {
resultList.addAll(future.get());
}
return resultList;
}
}
}
上述表中后两个方法返回实现了ScheduledExecutorService接口的对象。
例子
import java.util.Date;
import java.util.concurrent.*;
public class ScheduledExecutorTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
String time = new Date().toString();
System.out.println(time);
return time;
}
};
// 预定在指定时间之后执行任务
ScheduledFuture<String> future = scheduledExecutorService.schedule(callable, 1000, TimeUnit.MILLISECONDS);
Runnable runnable1 = new Runnable() {
@Override
public void run() {
String time = new Date().toString();
System.out.println("scheduleAtFixedRate() " + time);
}
};
//public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit);
// 周期长度是period
// 多少秒之后再执行, 是从上一个任务开始时开始计算
ScheduledFuture<?> future1 = scheduledExecutorService.scheduleAtFixedRate(runnable1, 0, 1, TimeUnit.MINUTES);
Runnable runnable2 = new Runnable() {
@Override
public void run() {
String time = new Date().toString();
System.out.println("scheduleWithFixedDelay() " + time);
}
};
// public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit);
// 两个周期之间有delay长度的时延
// 多少秒之后再执行, 是从上一个任务结束时开始计算
ScheduledFuture<?> future2 = scheduledExecutorService.scheduleWithFixedDelay(runnable2, 0, 1, TimeUnit.MINUTES);
}
}