java多线程解说【拾贰】_并发框架:Fork/Join


上篇文章:java多线程解说【拾壹】_并发容器


上文我们介绍了多线程编程中常用的并发容器,下面说一下多线程中常用的并发框架,主要有:


1.Fork/Join;

2.FutureTask


本文先说说Join/Fork框架


Fork/Join模式


Fork/Join框架是JDK7开始提供的用于并行还行任务的框架,原理就是把一个大任务拆分成若干个小任务同时执行,然后把执行结果汇总返回。


Fork/Join框架的核心是由下列两个类组成的:

ForkJoinPool:实现了ExecutorService接口和工作窃取算法(Work-Stealing Algorithm)。它管理工作者线程,并提供任务的状态信息,以及任务的执行信息。
ForkJoinTask:将在ForkJoinPool中执行的任务的基类。

ForkJoinWorkerThread:执行任务的线程


对于执行任务的Task,根据是否有返回结果的不同,决定需要继承下面2个类之一。

RecursiveAction:用于任务没有返回结果的场景。
RecursiveTask:用于任务有返回结果的场景。



一个例子


下面是一个使用Fork/Join框架的例子,用于统计一个文件夹中文件的个数。这里是判断,当文件夹下又出现文件夹时,则fork出一个子任务同时运行:


public class CountFileTask extends RecursiveTask<Integer> {  
    
	private static final long serialVersionUID = 1L;
	private File file;  

	private int    sum  = 0;  
  
    public CountFileTask(File f) {  
        this.file = f;  
    }  
    
    public CountFileTask() {  
    }  
  
    @Override  
    protected Integer compute() {  
        Integer    sum  = 0;  
        File[] list = file.listFiles();  
  
        for (File f : list) {  
            if (f.isDirectory()) {  
                CountFileTask cft = new CountFileTask(f);  
                cft.fork();  
                sum += cft.join();  
            } else{
            	sum++;  
            }
        }  
  
        return sum;  
    }  
    
    public Integer computeCommon(File file2){
        File[] list = file2.listFiles();  
        
        for (File f : list) {  
            if (f.isDirectory()) {  
            	computeCommon(f);
            } else{
            	sum++;  
            }
        }  
        
        return sum;
    }
  
    public static void main(String[] args) {  
        ForkJoinPool    forkJoinPool = new ForkJoinPool();  
        CountFileTask   task         = new CountFileTask(new File("D:/my workspaces"));  
        long            start        = System.currentTimeMillis();  
        Future<Integer> result       = forkJoinPool.submit(task);  
        try {  
            System.out.println(result.get());
            long duration = System.currentTimeMillis() - start;  
            System.out.println("time cost: " + duration + " ms");  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        } catch (ExecutionException e) {  
            e.printStackTrace();  
        }  
    }  
}  


Fork/Join框架的原理


ForkJoinPool内部维护了一个ForkJoinTask数组和ForkJoinWorkerThread数组。当执行fork方法时,先把子任务放到ForkJoinTask数组里面,然后在ForkJoinWorkerThread数组里唤醒或创建一个线程来执行它;执行join方法时,先判断当前线程的状态:


1.如果任务状态是已完成,则直接返回任务结果。
2.如果任务状态是被取消,则直接抛出CancellationException。
3.如果任务状态是抛出异常,则直接抛出对应的异常。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值