Fork/Join框架使用

以下是我对forkJoin的总结,不全,详情参见 java7 Concurrency CookBook

Fork/Join(分解和合并框架)
   通过分治技术将问题拆分成小任务的问题
   与执行器框架不同的是工作窃取算法
Fork/Join框架执行任务的限制
#任务只能使用fork()和join()操作当作同步机制,如果使用其他的同步机制
 工作者线程就不能执行其他任务。
#任务不能执行IO操作,比如文件读写
#任务不能抛出非运行时异常



Fork/Join框架的核心由下列两个类组成
#ForkJoinPool:这个类实现ExecutorService接口和工作窃取算法
#ForkJoinTask:这个类是一个将在ForkJoinPool中执行任务的基类
为了实现Fork/Join任务,需要实现一个以下两个类之一的子类(类似run方法和call方法)
 #RecursiveAction:用于任务没有返回结果的场景
 #RecursiveTask:用于任务有返回结果的场景


工作窃取算法的原理:
当一个主任务等待它的子任务时,执行这个主任务的工作者线程接收另一个等待执行的任务并开始执行
(主线程可以帮助子线程执行任务,这比Runnable和Callable对象更高效)


public class Product
{
private String name;
private double price;


public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public String getPrice(){
return price;
}
public void setPrice(double price){
this.price=price;
}

}
//产生产品
public class ProductListGenerator
{
public List<Product> generate(int size){
List<Product> ret = new ArrayList<Product>();
for(int i=0;i<size;i++){
Product product = new Product();
product.setName("product"+i);
product.setPrice(10);
ret.add(product);
}
return ret;
}
}


//继承RecursiveAction(无返回值) 覆盖compute方法
public class Task extends RecursiveAction
{ //RecursiveAction的父类ForkJoinTask实现了Serializable
private static final long serialVersionUID = 1L;


private List<Product> products;
//使用first和last进行分块
private int first;
private int last;


private double increment;


public Task(List<product> products,int first,int last,double increment){
this.products=products;
this.first=first;
this.last=last;
this.increment=increment;
}

//递归任务拆分是该框架中比较核心的东西
//加入last比first大10,进行任务拆分
@Override
protected void compute(){
if(last-first<10){
updatePrice();
}else{
int middle = (first+last)/2;
System.out.prinf("%s\n",getQueuedTaskCount());
Task t1=new Task(products,first,middle+1,increment);
Task t2=new Task(products,middle+1,last,increment);
invokeAll(t1,t2);//同步执行拆分任务
}
}


private void updatePrices(){
for(int i=first;i<last;i++){
Product product=products.get(i);
product.setPrice(product.getPrice()*(1+incement));
}
}

}





public class Main
{
public static void main(String[] args) 
{


ProductListGenerator generator = new ProductListGenerator();
List<Product> products = generator.generate(10000);

Task task = new Task(prducts,0,products.size(),0.20);


ForkJoinPool pool = new ForkJoinPool();
pool.execute(task);


pool.shutdown();


//调用isCompletedNormally()检查任务完成并且没有错
if (task.isCompletedNormally())
{
System.out.printf("finsh");
}


//打印不是12的产品信息
for(int i=0;i<products.size();i++){
Product product = products.get(i);
if(product.getPrice()!=12){
System.out.printf("product: %s: %f\n",product.getName(),product.getPrice());
}
}


}
}


//当使用异步的方式时,无法使用ForkJoinPool类的工作窃取算法
//异步运行任务


public class FolderProcessor extends RecursiveTask<List<String>>
{
private static final long serialVersionUID=1L;


private String path;
//存储文件的扩展名
private String extendsion;


public FolderProcessor(String path,String extendsion){
this.path = path;
this.extendsion=extendsion;
}
//实现compute方法
@Override
protected List<String> compute(){


List<String> list = new ArrayL<>();


List<FolderProcessor> tasks = new ArrayList<>();


File file = new File(path);
File content[] = file.listFiles();


if(content!=null){
for(int i=0;i<content.length;i++){
if(content[i].isDirectory()){
FolderProcessor task = new FolderProcessor(
content[i].getAbsolutePath(),extension);
task.fork();//用fork将任务发送到线程池
tasks.add(task);
}else{
if(checkFile(content[i].getName())){
list.add(content[i].getAbsolutePath())
}
}
}
}

if(tasks.size()>50){
System.out.printf(file.getAbsolutePath(),task.size());
}


addResultFormatTasks(list,tasks);
return list;
}
private void addResultsFormTasks(List<String> list,List<FolderProcess>tasks){
for(FolderProcessor item:tasks){
//调用join方法等待任务执行结束,并返回结果,将结果增加到字符列表中
list.addAll(item.join());
}
 
private boolean checkFile(String name){
return name.endsWith(extendsion);
}
}


public class Main
{
public static void main(String[] args){
ForkJoinPool pool = new ForkJoinPool();


FolderProcessor system=new FolderProcessor("c:\\Windows","log");
FolderProcessor apps=new FolderProcessor("c:\\Program Files","log");
FolderProcessor documents=new FolderProcessor("c:\\Documents And Settings","log");

pool.execute(system);
pool.execute(system);
pool.execute(system);


do{
//打印线程池信息
}
while((!system.isDone())||(!apps.isDone())||(!document.isDone()));


pool.shutdown();


//在控制台打印每个任务产生的结果的大小
List<String> results;
results=system.join();
System.out.printf("%d files found.\n",results.size());


results=apps.join();
System.out.printf("%d files found.\n",results.size());


results=documents.join();
System.out.printf("%d files found.\n",results.size());
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值