JAva fork/joinフレームワークの下での集計並べ替えと高速並べ替え

4722 ワード

前言
  • Fork/JoinフレームワークはJava 7が提供する同時実行タスクのためのフレームワークであり、その主な思想は大タスクをいくつかの小タスクに分割し、最終的に各小タスクの結果をまとめて大タスクの結果を得るフレームワークである.
  • データ構造に精通している友人は、その集計ソートも同様の考え方であることをすぐに考えることができるかもしれないので、fork/joinフレームワークで並列(単一CPU下では同時)の集計ソートを実現できるかどうかを自然に考え、この考えに基づいて、ついでにソートアルゴリズムを書いた.
    集計ソート
  • 次はコード
  • です.
    public class MergeSortTask extends RecursiveTask{
        //       task  RecursiveAction  
        private int[] array;
        private int left;
        private int right;
    
        public static void main(String[] args) {
            int[] a = {4,2,1,4,7,5,3,8,2,7,1,78,89,6,5,4,8,5};
            ForkJoinPool forkJoinPool = new ForkJoinPool();
            MergeSortTask task = new MergeSortTask(a, 0, a.length-1);
            Future result = forkJoinPool.submit(task);
            try {
                result.get();
                for (int n : a) {
                    System.out.print(n + " ");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    
        public MergeSortTask(int[] array, int left, int right) {
            this.array = array;
            this.left = left;
            this.right = right;
        }
    
        @Override
        protected Void compute() {
            boolean isNeedSplit = right - left >= 1;
            if (isNeedSplit) {
                int mid = (left + right)/2;
                MergeSortTask mergeSortTask1 = new MergeSortTask(array, left, mid);
                MergeSortTask mergeSortTask2 = new MergeSortTask(array, mid+1, right);
                mergeSortTask1.fork();
                mergeSortTask2.fork();
                mergeSortTask1.join();
                mergeSortTask2.join();
                merge(array, left, mid, right);
            }else {
                int mid = (left+right)/2;
                merge(array, left, mid, right);
            }
            return null;
        }
    
        public static void merge(int a[], int left, int mid, int right) {
            int len = right - left + 1;
            int temp[] = new int[len];
            int i = left;
            int j = mid + 1;
            int index = 0;
            while(i<=mid && j <= right) {
                temp[index++] = a[i] <= a[j] ? a[i++] : a[j++];
            }
            while (i <= mid) {
                temp[index++] = a[i++];
            }
            while (j<=right) {
                temp[index++] = a[j++];
            }
            for (int k = 0; k
  • 実は上のこのコードはまだ多くの問題があります.例えば、結果を返さないタスクに使用して、RecursiveActionを継承したほうがいいですが、初めての試みなので、置いておきましょう.

  • クイックソート
  • 実際に考えてみると、早列もfork/joinフレームワークで実現できるようです.
  • 次はコード
  • です.
    public class QuickSortTask extends RecursiveAction{
    
        private int[] array;
        private int left;
        private int right;
    
        public QuickSortTask(int[] array, int left, int right) {
            this.array = array;
            this.left = left;
            this.right = right;
        }
    
        @Override
        protected void compute() {
            int pivot = partition(array, left, right);
            QuickSortTask task1 = null;
            QuickSortTask task2 = null;
            if (pivot - left > 1) {
                task1 = new QuickSortTask(array, left, pivot-1);
                task1.fork();
            }
            if (right - pivot > 1) {
                task2 = new QuickSortTask(array, pivot+1, right);
                task2.fork();
            }
            if (task1 != null && !task1.isDone()) {
                task1.join();
            }
            if (task2 != null && !task2.isDone()) {
                task2.join();
            }
        }
    
        public static int partition(int[] a, int left, int right) {
            int pivot = a[left];
            while (left < right) {
                while (left < right && a[right] >= pivot) {
                    right--;
                }
                swap(a, left, right);
                while (left < right && a[left] <= pivot) {
                    left++;
                }
                swap(a, left, right);
            }
            return left;
        }
    
        public static void swap(int[] a, int i, int j) {
            int temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    
        public static void main(String[] args) {
            int[] a = {4,2,1,4,7,5,3,8,2,7,1,78,89,6,5,4,8,5};
            ForkJoinPool forkJoinPool = new ForkJoinPool();
            QuickSortTask task = new QuickSortTask(a, 0, a.length-1);
            Future result = forkJoinPool.submit(task);
            try {
                result.get();
                for (int n : a) {
                    System.out.print(n + " ");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }