使用fork/join框架对大型浮点数数组排序排序

问题描述

使用fork/join框架对大型浮点数数组排序排序

这个例子是《java7 编程高级进阶》一书第474页的例子。代码如下:
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveAction;

public class Daemon {

private static ForkJoinPool threadPool;
private static final int THRESHOLD=16;

private static void sort(Comparable[] objectArray){
    Comparable[] destArray=new Comparable[objectArray.length];
    threadPool.invoke(new SortTask(objectArray,destArray,0,objectArray.length-1));
    //Future future=threadPool.submit(new SortTask(objectArray,destArray,0,objectArray.length-1));

}

static class SortTask extends RecursiveAction{
    private Comparable[] sourceArray;
    private Comparable[] destArray;
    private int lowerIndex,upperIndex;

    public SortTask(Comparable[] sourceArray,Comparable[] destArray,int lowerIndex,int upperIndex){
        this.sourceArray=sourceArray;
        this.destArray=destArray;
        this.lowerIndex=lowerIndex;
        this.upperIndex=upperIndex;
    }

    @Override
    protected void compute(){
        if(upperIndex-lowerIndex<THRESHOLD){
            insertionSort(sourceArray,lowerIndex,upperIndex);
            return;
        }

        int midIndex=(lowerIndex+upperIndex)>>>1;//无符号右移
        SortTask leftTask=new SortTask(sourceArray,destArray,lowerIndex,midIndex);
        SortTask rightTask=new SortTask(sourceArray,destArray,midIndex+1,upperIndex);
        leftTask.fork();
        rightTask.fork();

        leftTask.join();
        rightTask.join();

        merge(sourceArray,destArray,lowerIndex,midIndex,upperIndex);
    }
}//类结束

private static void merge(Comparable[] sourceArray,Comparable[] destArray,int lowerIndex,int midIndex,int upperIndex){
    if(sourceArray[midIndex].compareTo(sourceArray[midIndex+1])<=0){
        return;
    }

    System.arraycopy(sourceArray, lowerIndex, destArray, lowerIndex, midIndex-lowerIndex+1);
    int i=lowerIndex;
    int j=midIndex;
    int k=lowerIndex;

    while(k<j && j<=upperIndex){
        if(destArray[i].compareTo(sourceArray[j])<=0){
            sourceArray[k++]=destArray[i++];
        }else{
            sourceArray[k++]=sourceArray[j++];
        }
    }

    System.arraycopy(destArray, i, sourceArray, k, j-k);
}

private static void insertionSort(Comparable[] objectArray,int lowerIndex,int upperIndex){
    for(int i=lowerIndex+1;i<=upperIndex;i++){
        int j=i;
        Comparable tempObject=objectArray[j];
        while(j>lowerIndex && tempObject.compareTo(objectArray[j-1])<0){
            objectArray[j]=objectArray[j-1];
            --j;
        }
        objectArray[j]=tempObject;
    }
}

public static Double[] createRandomData(int length){
    Double[] data=new Double[length];
    for(int i=0;i<data.length;i++){
        data[i]=length*Math.random();
    }
    return data;
}

public static void main(String[] args) throws InterruptedException {

    int processors=Runtime.getRuntime().availableProcessors();
    System.out.println("Number of processors: "+processors);

    threadPool=new ForkJoinPool(processors);
    Double[] data=createRandomData(30);

    System.out.println("Original unsorted data: ");
    for (Double d: data){
        System.out.printf("%3.2f ",d);
    }

    sort(data);

    System.out.println("nSorted Array: ");
    for(Double d:data){
        System.out.printf("%3.2f ", d);
    }
}

}


但是输出结果有问题:

为了减少输出,我设定待排序数量为30.可以看到,排序后的数组中前15个是有序的,后15个也是有序的。但是整体而言就不是有序的了。所以我猜想问题就出现在合并那一步,即merge()函数那里。但是我分析了一下,这个函数逻辑上没有问题,是不是因为处于多线程环境而导致出现问题呢?期待大家能够给予解惑,不甚感激!

解决方案

你的问题是什么呢?还是只是分享你发现了一个bug

解决方案二:

不好意思,因为发帖的时候突然有事,就没写完整。这里补上。

解决方案三:

不好意思,因为发帖的时候突然有事,就没写完整。这里补上。

解决方案四:

不好意思,因为发帖的时候突然有事,就没写完整。这里补上。

时间: 2024-09-20 17:43:34

使用fork/join框架对大型浮点数数组排序排序的相关文章

聊聊并发(八)——Fork/Join框架介绍

本文首发于InfoQ 1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过Fork和Join这两个单词来理解下Fork/Join框架,Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果.比如计算1+2+..+10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和,最终汇

Fork/Join框架简介

1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务 ,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过Fork和Join这两个单词来理解下Fork/Join框架,Fork就是把一个大任务切分为若干子任务 并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果.比如计算1+2+..+ 10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和,最终汇总这10个子任务

Java Fork/Join框架_java

Fork/Join框架是ExecutorService接口的一个实现,通过它我们可以实现多进程.Fork/Join可以用来将一个大任务递归的拆分为多个小任务,目标是充分利用所有的资源尽可能增强应用的性能. 和任何ExecutorService接口的实现一样,Fork/Join也会使用线程池来分布式的管理工作线程.Fork/Join框架的独特之处在于它使用了work-stealing(工作窃取)算法.通过这个算法,工作线程在无事可做时可以窃取其它正在繁忙的线程的任务来执行. Fork/Join框架

Fork/Join框架(三)加入任务的结果

加入任务的结果 Fork/Join框架提供了执行返回一个结果的任务的能力.这些任务的类型是实现了RecursiveTask类.这个类继承了ForkJoinTask类和实现了执行者框架提供的Future接口. 在任务中,你必须使用Java API方法推荐的结构: 1 If (problem size < size){ 2 tasks=Divide(task); 3 execute(tasks); 4 groupResults() 5 return result; 6 } else { 7 reso

定制并发类(八)自定义在 Fork/Join 框架中运行的任务

声明:本文是< Java 7 Concurrency Cookbook>的第七章, 作者: Javier Fernández González 译者:郑玉婷 自定义在 Fork/Join 框架中运行的任务 执行者框架分开了任务的创建和运行.这样,你只要实现 Runnable 对象来使用 Executor 对象.你可以发送 Runnable 任务给执行者,然后它会创建,管理,并终结必要的线程来执行这些任务. Java 7 在 Fork/Join 框架中提供了特殊的执行者.这个框架是设计用来解决那

定制并发类(七)实现ThreadFactory接口生成自定义的线程给Fork/Join框架

声明:本文是< Java 7 Concurrency Cookbook>的第七章,作者: Javier Fernández González     译者:许巧辉 实现ThreadFactory接口生成自定义的线程给Fork/Join框架 Fork/Join框架是Java7中最有趣的特征之一.它是Executor和ExecutorService接口的一个实现,允许你执行Callable和Runnable任务而不用管理这些执行线程. 这个执行者面向执行能被拆分成更小部分的任务.主要组件如下: 一

Fork/Join框架(四)异步运行任务

异步运行任务 当你在ForkJoinPool中执行ForkJoinTask时,你可以使用同步或异步方式来实现.当你使用同步方式时,提交任务给池的方法直到提交的任务完成它的执行,才会返回结果.当你使用异步方式时,提交任务给执行者的方法将立即返回,所以这个任务可以继续执行. 你应该意识到这两个方法有很大的区别,当你使用同步方法,调用这些方法(比如:invokeAll()方法)的任务将被阻塞,直到提交给池的任务完成它的执行.这允许ForkJoinPool类使用work-stealing算法,分配一个新

Java Fork Join 框架(四)性能

原文 http://gee.cs.oswego.edu/dl/papers/fj.pdf   作者:Doug Lea   译者:萧欢 4性能 如今,随着编译器与Java虚拟机性能的不断提升,性能测试结果也仅仅只能适用一时.但是,本节中所提到的测试结果数据却能揭示Fork/join框架的基本特性. 下面表格中简单介绍了在下文将会用到的一组fork/join测试程序.这些程序是从util.concurrent包里的示例代码改编而来,用来展示fork/join框架在解决不同类型的问题模型时所表现的差异

Fork/Join框架(一)引言

在这个章节中,我们将覆盖: 创建一个Fork/Join池 加入任务的结果 异步运行任务 任务抛出异常 取消任务 引言 通常,当你实现一个简单的并发应用程序,你实现一些Runnable对象和相应的 Thread对象.在你的程序中,你控制这些线程的创建.执行和状态.Java 5引入了Executor和ExecutorService接口及其实现类进行了改进(比如:ThreadPoolExecutor类). 执行者框架将任务的创建与执行分离.有了它,你只要实现Runnable对象和使用Executor对