并发编程的一种编程方式是把任务拆分为一些列的小任务,即Runnable,然后在提交给一个Executor执行。Executor在执行时使用内部的线程池完成操作。
Executor在客户端和任务执行之间提供了一个间接层;与客户端直接执行任务不同,这个中介对象将执行任务。Executor允许你管理异步任务的执行,而无需显式的管理线程的生命周期。
Future、Callable、ExecutorService的用法:
这三个接口位于java.util.concurrent包下,concurrent是同时发生的意思。
InterruptedException, ExecutionException是线程被中断抛出的异常和线程被中断后仍尝试获取线程结果抛出的异常
import java.util.concurrent.*;
class FindMaxTask implements Callable<Integer>{
private int[] data;
private int start;
private int end;
FindMaxTask(int[] data, int start, int end){
this.data = data;
this.start = start;
this.end = end;
}
@Override
public Integer call() throws Exception {
int max = Integer.MIN_VALUE;
for (int i = start; i < end; i++){
if (data[i] > max){
max = data[i];
}
}
return max;
}
}
public class MultithreadedMaxFinder {
public static int getMax(int[] data) throws InterruptedException, ExecutionException{
if (data.length == 1){
return data[0];
}else if (data.length == 0){
throw new IllegalArgumentException();
}
// 将任务分解为两部分
FindMaxTask task1 = new FindMaxTask(data, 0, data.length / 2);
FindMaxTask task2 = new FindMaxTask(data, data.length / 2, data.length);
// 创建一个容量为2的线程池
ExecutorService service = Executors.newFixedThreadPool(2);
Future<Integer> future1 = service.submit(task1);
Future<Integer> future2 = service.submit(task2);
return Math.max(future1.get(), future2.get());
}
public static void main(String[] args) {
int[] data = {10, 6, 9, 65, 89, 111, 54, 23, 2, 100};
try {
System.out.println(getMax(data));
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
该程序运行结果为:111
压缩一个目录下的文件示例:
package thread;
import java.io.*;
import java.util.concurrent.*;
import java.util.zip.*;
class GZipRunnable implements Runnable {
private final File input;
public GZipRunnable(File input) {
this.input = input;
}
@Override
public void run() {
// 不压缩已经压缩的文件
if (!input.getName().endsWith(".zip")) {
File output = new File(input.getParentFile(), input.getName()
+ ".zip");
if (!output.exists()) {// 不覆盖已经存在的文件
try (InputStream in = new BufferedInputStream(
new FileInputStream(input));
OutputStream out = new BufferedOutputStream(
new GZIPOutputStream(new FileOutputStream(
output)));) {
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class GZipAllFiles {
public final static int THREAD_COUNT = 4;// 线程数量
public static void main(String[] args) {
// 容量为4的线程池
ExecutorService pool = Executors.newFixedThreadPool(THREAD_COUNT);
File f = new File("G:\\Workspaces\\MyEclipse 2015\\MySocket\\Files");
// 判断f是否存在
if (f.exists()) {
if (f.isDirectory()) {
File[] files = f.listFiles();
for (int i = 0; i < files.length; i++) {
if (!files[i].isDirectory()) {
Runnable task = new GZipRunnable(files[i]);
pool.submit(task);
}
}
} else {
Runnable task = new GZipRunnable(f);
pool.submit(task);
}
} else {
System.out.println("文件或目录不存在");
}
// 关闭线程池
pool.shutdown();
}
}
示例结果: