Callable与Runnable类似,但是有返回值,其接口是一个参数化的类型,只有一个call方法(类似Runnable中的run方法)
Future保存异步计算的结果,可以启动一个计算(callable),将Future对象交付给线程即可。当计算结束时,通过get方法获取计算结果。若计算未完成,则调用被阻塞,直到完成。可以通过isDone方法判断计算是否完成。
FutureTask包装器,可将Callable转换为Future和Runnable,同时实现二者的接口。
Callable_1 callable1=new Callable_1();
FutureTask<Integer> result=new FutureTask<>(callable1);
new Thread(result).start();
result.get();
eg1:通过callable和future打印一组数据
package com.lmr.thread;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class Callable_Future_1 {
public static void main(String[] args) {
Callable_1 callable1=new Callable_1();
FutureTask<Integer> result=new FutureTask<>(callable1);
new Thread(result).start();//启动result的FutureTask对象,去执行callable1的call方法
System.out.println("main thread is running");
try {
System.out.println("result: "+result.get());//获取结果
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("main thread is ending");
}
}
public class Callable_1 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
// TODO Auto-generated method stub
System.out.println("callable is runing");
int sum=0;
for(int i=0;i<10;i++){
Thread.sleep(1000);
sum+=i;
System.out.println(i+" - "+sum);//每隔1秒打印数据
}
return sum;
}
}
通过打印的结果,我们发现到程序跑到get方法时,并没有获取到结果,而是等callable1的call方法执行完毕后,才会打印结果
callable is runing
main thread is running
0 - 0
1 - 1
2 - 3
3 - 6
4 - 10
5 - 15
6 - 21
7 - 28
8 - 36
9 - 45
result: 45
main thread is ending
eg2:搜索指定目录下所有文件内容,计算关键字的个数
package com.lmr.thread;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class Callable_Future_2 {
public static void main(String[] args) {
String directory="E:\\Java_Swing\\src\\com\\swing";
String keyword="JPanel";
MatchCount counter=new MatchCount(new File(directory), keyword);
FutureTask<Integer> task=new FutureTask<>(counter);
Thread t=new Thread(task);
t.start();
try {
System.out.println("------------- "+task.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class MatchCount implements Callable<Integer>{
private File directory;
private String keyword;
private int count;//关键字数目
public MatchCount(File directory,String keyword) {
// TODO Auto-generated constructor stub
this.directory=directory;
this.keyword=keyword;
}
@Override
public Integer call() throws Exception {
// TODO Auto-generated method stub
count=0;
try{
File[] files=directory.listFiles();
List<Future<Integer>> results=new ArrayList<>();//Future对象List
for(File file:files){
if(file.isDirectory()){
MatchCount counter=new MatchCount(file, keyword);//递归遍历
FutureTask<Integer> task=new FutureTask<>(counter);
results.add(task);
Thread t=new Thread(task);
t.start();
}
else{
if(search(file)){//若是文件,则去计算数目
count+=searchsum(file);
}
}
}
for(Future<Integer> result:results){//当该目录下所有文件的Future计算完后,累加数目
count+=result.get();
}
}
catch (Exception e) {
// TODO: handle exception
}
return count;
}
public boolean search(File file){//判断文件是否有关键字
try{
Scanner in=new Scanner(file);
boolean found=false;
while(!found&&in.hasNextLine()){
String line=in.nextLine();
if(line.contains(keyword)){
found=true;
}
}
return found;
}
catch (Exception e) {
// TODO: handle exception
return false;
}
}
public int searchsum(File file) throws FileNotFoundException {//关键字计数
Scanner in = new Scanner(file);
int found = 0;
while (in.hasNextLine()) {
String line = in.nextLine();
while (line.contains(keyword)) {
System.out.println(line);
line=line.substring(line.indexOf(keyword)+keyword.length());
found++;
}
}
return found;
}
}