1. 程式人生 > >Java粗淺認識-併發程式設計(三)

Java粗淺認識-併發程式設計(三)

執行緒啟動

實現java.lang.Runnable

常用方式

    public static class Task implements Runnable {
        @Override
        public void run() {
            System.out.println("執行任務。");
        }
    }

啟動執行緒

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //實現Runnable
        Thread thread = new Thread(new Task());
        thread.start();
}

 繼承java.lang.Thread

    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("執行任務。");
        }
    }

啟動執行緒

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //繼承Thread
        MyThread myThread = new MyThread();
        myThread.start();
}

實現java.util.concurrent.Callable

帶返回值的介面,在java.util.concurrent.ExecutorService內執行。

    public static class CallableTask implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            //計算結果
            return 0;
        }
    }

啟動執行緒

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //實現Callable,配合執行緒池(executorService介面的submit)使用,具有返回值
        CallableTask callableTask = new CallableTask();
        ExecutorService executorService = new ThreadPoolExecutor(4, 8, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1 << 4));
        Future<Integer> integerFuture = executorService.submit(callableTask);
        System.out.println(integerFuture.get());
        executorService.shutdown();
}

 java.util.Timer定時器(java 1.3)

現在不建議使用,建議用java.util.concurrent.ScheduledExecutorService代替。

        //Timer,不建議使用了,無法控制,建議是用java.util.concurrent.ScheduledExecutorService代替
        Timer timer = new Timer();
        //10s後執行
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("定時任務");
            }
        }, 1000 * 10);

java.util.concurrent.ForkJoinPool

在java1.7新增的應該屬於執行緒池範疇,寫在這裡了,fork,join,後面詳細講講它的實現,它執行java.util.concurrent.ForkJoinTask

執行任務分類java.util.concurrent.RecursiveAction不帶返回值的遞迴操作,java.util.concurrent.RecursiveTask帶返回值的遞迴操作。

RecuiciveAction

RecurciveTask

接下來我們用分別用單執行緒ForkJoinPoll陣列排序求斐波拉契數列第n位數是什麼

單執行緒歸併排序

private static void mergeSort() {
        int[] array = randomArray(100, 100);
        mergeSort(array, 0, array.length - 1);
        printArray(array, "排序結果:");
    }

    private static void mergeSort(int[] array, int left, int right) {
        if (left >= right) {
            return;
        }
        int mid = left + ((right - left) >>> 1);
        //左邊排序
        mergeSort(array, left, mid);
        //右邊排序
        mergeSort(array, mid + 1, right);
        //左後排序後合併
        merge(array, left, mid, right);
    }

    private static void merge(int[] array, int left, int mid, int right) {
        int[] helper = new int[right - left + 1];
        int helperIndex = 0;
        int l = left;
        int r = mid + 1;
        while (l <= mid && r <= right) {
            helper[helperIndex++] = array[l] < array[r] ? array[l++] : array[r++];
        }
        while (l <= mid) {
            helper[helperIndex++] = array[l++];
        }

        while (r <= right) {
            helper[helperIndex++] = array[r++];
        }

        System.arraycopy(helper, 0, array, left, helper.length);
    }

ForkJoinPool排序

        //forkJoin多執行緒排序
        forkJoinPool.invoke(new MyRecursiveAction(array, 0, array.length - 1));
        printArray(array, "結果:");
/**
     * 沒有返回值的遞迴任務,排序
     */
    public static class MyRecursiveAction extends RecursiveAction {
        int[] array;
        int left;
        int right;

        public MyRecursiveAction(int[] array, int left, int right) {
            this.array = array;
            this.left = left;
            this.right = right;
        }

        @Override
        protected void compute() {
            if (left >= right) {
                return;
            }
            int mid = left + ((right - left) >>> 1);
            invokeAll(new MyRecursiveAction(array, left, mid), new MyRecursiveAction(array, mid + 1, right));
            merge(array, left, mid, right);
        }

        private void merge(int[] array, int left, int mid, int right) {
            int[] helper = new int[right - left + 1];
            int helperIndex = 0;
            int l = left;
            int r = mid + 1;
            while (l <= mid && r <= right) {
                helper[helperIndex++] = array[l] < array[r] ? array[l++] : array[r++];
            }
            while (l <= mid) {
                helper[helperIndex++] = array[l++];
            }

            while (r <= right) {
                helper[helperIndex++] = array[r++];
            }
            System.arraycopy(helper, 0, array, left, helper.length);
        }
    }

單執行緒斐波拉契數列求值

    private static int fibonacci(int value) {
        if (value == 1 || value == 2) {
            return 1;
        }
        return fibonacci(value - 1) + fibonacci(value - 2);
    }

ForkJoinPool斐波拉契數列求值

        //forkJoin多執行緒求斐波拉契數列第n個數
        ForkJoinTask<Integer> forkJoinTask= forkJoinPool.submit(new MyRecursiveTask(10));
        System.out.println("結果"+forkJoinTask.get());
 /**
     * 帶返回值遞迴任務,累加
     */
    public static class MyRecursiveTask extends RecursiveTask<Integer> {
        private int value;

        public MyRecursiveTask(int value) {
            this.value = value;
        }

        @Override
        protected Integer compute() {
            if (value == 1 || value == 2) {
                return 1;
            }
            MyRecursiveTask task1 = new MyRecursiveTask(value - 1);
            task1.fork();
            MyRecursiveTask task2 = new MyRecursiveTask(value - 2);
            task2.fork();
            return task1.join() + task2.join();
        }
    }

總結

Java中執行緒啟動就講完了,下一講,程序內執行緒間通訊。

以下是完成程式碼:

/**
 * @author baopz
 */
public class UsingThread {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //實現Runnable
        Thread thread = new Thread(new Task());
        thread.start();
        //繼承Thread
        MyThread myThread = new MyThread();
        myThread.start();
        //實現Callable,配合執行緒池(executorService介面的submit)使用,具有返回值
        CallableTask callableTask = new CallableTask();
        ExecutorService executorService = new ThreadPoolExecutor(4, 8, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1 << 4));
        Future<Integer> integerFuture = executorService.submit(callableTask);
        System.out.println(integerFuture.get());
        executorService.shutdown();
        //Timer,不建議使用了,無法控制,建議是用java.util.concurrent.ScheduledExecutorService代替
        Timer timer = new Timer();
        //10s後執行
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("定時任務");
            }
        }, 1000 * 10);

        //1.7,先分開,後合併,歸併
        ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
        int[] array = randomArray(100, 100);

        //單執行緒歸併排序
        mergeSort();

        //forkJoin多執行緒排序
        forkJoinPool.invoke(new MyRecursiveAction(array, 0, array.length - 1));
        printArray(array, "結果:");

        //單執行緒斐波拉契數列,第n個數是什麼?1、1、2、3、5、8、13、21、34、55
        System.out.println(fibonacci(10));

        //forkJoin多執行緒求斐波拉契數列第n個數
        ForkJoinTask<Integer> forkJoinTask= forkJoinPool.submit(new MyRecursiveTask(10));
        System.out.println("結果"+forkJoinTask.get());

    }

    private static int fibonacci(int value) {
        if (value == 1 || value == 2) {
            return 1;
        }
        return fibonacci(value - 1) + fibonacci(value - 2);
    }

    private static int[] randomArray(int size, int bound) {
        int[] array = new int[100];
        Random random = new Random(System.currentTimeMillis());
        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt(1000);
        }
        printArray(array, "隨機陣列:");
        return array;
    }

    private static void printArray(int[] array, String prefix) {
        if (prefix != null) {
            System.out.println(prefix);
        }
        for (int i : array) {
            System.out.print(i + " ");
        }
        System.out.println();
    }

    private static void mergeSort() {
        int[] array = randomArray(100, 100);
        mergeSort(array, 0, array.length - 1);
        printArray(array, "排序結果:");
    }

    private static void mergeSort(int[] array, int left, int right) {
        if (left >= right) {
            return;
        }
        int mid = left + ((right - left) >>> 1);
        //左邊排序
        mergeSort(array, left, mid);
        //右邊排序
        mergeSort(array, mid + 1, right);
        //左後排序後合併
        merge(array, left, mid, right);
    }

    private static void merge(int[] array, int left, int mid, int right) {
        int[] helper = new int[right - left + 1];
        int helperIndex = 0;
        int l = left;
        int r = mid + 1;
        while (l <= mid && r <= right) {
            helper[helperIndex++] = array[l] < array[r] ? array[l++] : array[r++];
        }
        while (l <= mid) {
            helper[helperIndex++] = array[l++];
        }

        while (r <= right) {
            helper[helperIndex++] = array[r++];
        }

        System.arraycopy(helper, 0, array, left, helper.length);
    }

    /**
     * 帶返回值遞迴任務,累加
     */
    public static class MyRecursiveTask extends RecursiveTask<Integer> {
        private int value;

        public MyRecursiveTask(int value) {
            this.value = value;
        }

        @Override
        protected Integer compute() {
            if (value == 1 || value == 2) {
                return 1;
            }
            MyRecursiveTask task1 = new MyRecursiveTask(value - 1);
            task1.fork();
            MyRecursiveTask task2 = new MyRecursiveTask(value - 2);
            task2.fork();
            return task1.join() + task2.join();
        }
    }

    /**
     * 沒有返回值的遞迴任務,排序
     */
    public static class MyRecursiveAction extends RecursiveAction {
        int[] array;
        int left;
        int right;

        public MyRecursiveAction(int[] array, int left, int right) {
            this.array = array;
            this.left = left;
            this.right = right;
        }

        @Override
        protected void compute() {
            if (left >= right) {
                return;
            }
            int mid = left + ((right - left) >>> 1);
            invokeAll(new MyRecursiveAction(array, left, mid), new MyRecursiveAction(array, mid + 1, right));
            merge(array, left, mid, right);
        }

        private void merge(int[] array, int left, int mid, int right) {
            int[] helper = new int[right - left + 1];
            int helperIndex = 0;
            int l = left;
            int r = mid + 1;
            while (l <= mid && r <= right) {
                helper[helperIndex++] = array[l] < array[r] ? array[l++] : array[r++];
            }
            while (l <= mid) {
                helper[helperIndex++] = array[l++];
            }

            while (r <= right) {
                helper[helperIndex++] = array[r++];
            }
            System.arraycopy(helper, 0, array, left, helper.length);
        }
    }


    public static class CallableTask implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            return 0;
        }
    }

    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("執行任務。");
        }
    }

    public static class Task implements Runnable {
        @Override
        public void run() {
            System.out.println("執行任務。");
        }
    }
}