Fork/Join——ForkJoinPool核心方法(一)

ForkJoinPool核心方法

1.

方法
public vod execute(ForkJoinTask<?> task)
的使用

在ForkJoinPool.java類中的execute()方法是以異步的方式執行任務。

public class MyRun1 {
    public static void main(String[] args) {
        try {
            ForkJoinPool pool = new ForkJoinPool();
            pool.execute(new ActionA());
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class ActionA extends RecursiveAction {

    @Override
    protected void compute() {
        System.out.println("ThreadName=" + Thread.currentThread().getName());
    }
}

在這裏插入圖片描述

2.

方法
public void execute(Runnable task)
的使用
public class MyRun2 {
    public static void main(String[] args) throws InterruptedException {
        ForkJoinPool pool = new ForkJoinPool();
        pool.execute(() -> {
            System.out.println("ThreadName=" + Thread.currentThread().getName());
        });
        Thread.sleep(5000);
    }
}

在這裏插入圖片描述

3.

方法
public void execute(ForkJoinTask<?> task)
如何處理返回值
public class MyRun3 {
    public static void main(String[] args) {
        try {
            ActionB task = new ActionB();
            ForkJoinPool pool = new ForkJoinPool();
            pool.execute(task);
            //execute方法無返回值,想取得返回值得通過RecursiveTask對象
            System.out.println(System.currentTimeMillis());
            System.out.println(task.get());
            System.out.println(System.currentTimeMillis());
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class ActionB extends RecursiveTask<String> {

    @Override
    protected String compute() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "我是返回值";
    }
}

雖然public void execute(ForkJoinTask<?> task)方法無返回值,但還是可以通過RecursiveTask對象處理返回值。調用get()方法即阻塞。
在這裏插入圖片描述

4.

方法
public<T> ForkJoinTask<T> submit(ForkJoinTask<T> task)
的使用

方法execute()無返回值,submit()有返回值。

public class MyRun4 {
    public static void main(String[] args) {
        try {
            ActionC task = new ActionC();
            ForkJoinPool pool = new ForkJoinPool();
            ForkJoinTask<String> returnTask = pool.submit(task);
            System.out.println("begin " + System.currentTimeMillis());
            System.out.println(returnTask.get());
            System.out.println("end " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class ActionC extends RecursiveTask<String> {

    @Override
    protected String compute() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "我是返回值";
    }
}

在這裏插入圖片描述

5.

方法
public ForkJoinTask<?> submit(Runnable task)
的使用
public class MyRun5 {
    public static void main(String[] args) {
        try {
            ForkJoinPool pool = new ForkJoinPool();
            System.out.println("begin " + System.currentTimeMillis());
            ForkJoinTask<?> submit = pool.submit(() -> {
                try {
                    Thread.sleep(5000);
                    System.out.println("ThreadName=" + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            System.out.println(submit.get());
            System.out.println("end " + System.currentTimeMillis());
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

任務成功被運行,傳入Runnable接口雖然沒有返回值,但調用get()方法呈阻塞狀態。
在這裏插入圖片描述

6.

方法
public <T> ForkJoinTask<T> submit(Callable<T> task)
的使用
public class MyRun6 {
    public static void main(String[] args) {
        try {
            MyCallable callable = new MyCallable();
            ForkJoinPool pool = new ForkJoinPool();
            System.out.println("begin " + System.currentTimeMillis());
            ForkJoinTask<String> returnTask = pool.submit(callable);
            System.out.println(returnTask.get());
            System.out.println("end " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class MyCallable implements Callable<String> {

    @Override
    public String call() throws Exception {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "我是返回值callableVersion";
    }
}

在這裏插入圖片描述

7

方法
public <T> ForkJoiinTask<T> submit(Runnable task, T result)
的使用
public class MyRun7 {
    public static void main(String[] args) throws InterruptedException {
        UserInfo userInfo = new UserInfo();
        RunnableT runnableT = new RunnableT(userInfo);

        ForkJoinPool pool = new ForkJoinPool();
        pool.submit(runnableT, userInfo);
        //取不到值
        System.out.println("userinfo username=" + userInfo.getUsername());
        Thread.sleep(2000);
    }
}

class UserInfo {
    private String username;

    public UserInfo() {
    }

    public UserInfo(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

class RunnableT implements Runnable {
    private UserInfo userInfo;

    public RunnableT(UserInfo userInfo) {
        this.userInfo = userInfo;
    }

    @Override
    public void run() {
        try {
            userInfo.setUsername("設置的值");
            System.out.println("已經設置完結!");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在這裏插入圖片描述
運行結果是未取到值,因爲是異步運行的,所以要加一個延時:
在這裏插入圖片描述
在這裏插入圖片描述
成功取到值,但程序還是有一些問題,也就是sleep(的時間並不能真正的確定,因爲不知道Task任務執行完需要多少時間,更改代碼如下:

在這裏插入圖片描述
在這裏插入圖片描述

8.

方法
public <T> List<Futre<T>> invokeAll(Collection<? extends Calable<T>> tasks)
的使用

該方法具有阻塞特性。

public class MyRun8 {
    public static void main(String[] args) {
        try {
            List list = new ArrayList();
            list.add(new CallableC(5000));
            list.add(new CallableC(4000));
            list.add(new CallableC(3000));
            list.add(new CallableC(2000));
            list.add(new CallableC(1000));

            ForkJoinPool pool = new ForkJoinPool();
            List<Future<String>> listFuture = pool.invokeAll(list);
            for (int i = 0; i < listFuture.size(); i++) {
                System.out.println(listFuture.get(i).get() + " nowTime: " + System.currentTimeMillis());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class CallableC implements Callable<String> {
    private long sleepValue;

    public CallableC(long sleepValue) {
        this.sleepValue = sleepValue;
    }

    @Override
    public String call() throws Exception {
        try {
            System.out.println(Thread.currentThread().getName() + " sleep" + sleepValue + " nowTime: " +
                    System.currentTimeMillis());
            Thread.sleep(sleepValue);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "我是返回值";
    }
}

在這裏插入圖片描述

9.

方法
public void shutdown()
的使用
public class Test1 {
    public static void main(String[] args) throws InterruptedException {
        ForkJoinPool pool = new ForkJoinPool();
        MyRunnable1 r = new MyRunnable1();
        pool.submit(r);
        Thread.sleep(1000);
        pool.shutdown();
        System.out.println("main end!");
        Thread.sleep(Integer.MAX_VALUE);
    }
}

class MyRunnable1 implements Runnable {

    @Override
    public void run() {
        try {
            System.out.println("begin " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
            Thread.sleep(4000);
            System.out.println("end " + Thread.currentThread().getName() + " " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

調用shutdown()方法後任務依然運行,直到結束。
在這裏插入圖片描述

在這裏插入圖片描述
上面代碼運行後進程馬上被銷燬,說明對ForkJoinPool對象調用shutdown()方法後再執行任務時出現異常,進程也就馬.上銷燬了,而正在運行的線程任務也被銷燬掉了,運行的效果當然就是字符串“end” 沒有輸出,僅僅打印了“begin"。
在這裏插入圖片描述

爲了防止在關閉pool後再運行任務,可以加入一個判斷來解決進程意外銷燬的問題:

在這裏插入圖片描述
在這裏插入圖片描述
注意:shutdown()方法不具有中斷的效果,也就是shutdown()方法遇到MyRunnable1中的sleep()方法沒有發生中斷異常。

10.

方法
public List<Runnable> shutdownNow()
的使用
public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable111 myRunnable111 = new MyRunnable111();
        ForkJoinPool pool = new ForkJoinPool();
        pool.submit(myRunnable111);
        Thread.sleep(2000);
        pool.shutdownNow();
        System.out.println("main end");
        Thread.sleep(Integer.MAX_VALUE);
    }
}

class MyRunnable111 implements Runnable {

    @Override
    public void run() {
        try {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                String newString = new String();
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                Math.random();
                if (Thread.currentThread().isInterrupted() == true) {
                    System.out.println("任務沒有完成,就中斷了!");
                    throw new InterruptedException();
                }
            }
            System.out.println("任務完成了!");
        } catch (InterruptedException e) {
            System.out.println("進入Catch中斷了任務");
            e.printStackTrace();
        }
    }
}

class MyRunnable222 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < Integer.MAX_VALUE / 100; i++) {
            new String();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
            Math.random();
        }
        System.out.println("任務完成!");
    }
}

在這裏插入圖片描述

		MyRunnable222 myRunnable222 = new MyRunnable222();
        ForkJoinPool pool = new ForkJoinPool();
        pool.execute(myRunnable222);
        Thread.sleep(1000);
        pool.shutdownNow();
        System.out.println("main end");
        Thread.sleep(Integer.MAX_VALUE);    

在這裏插入圖片描述

MyRunnable222 myRunnable222 = new MyRunnable222();
ForkJoinPool pool = new ForkJoinPool();
pool.execute(myRunnable222);
Thread.sleep(1000);
pool.shutdownNow();//返回一個空的List
pool.execute(myRunnable222);
System.out.println("main end");
Thread.sleep(Integer.MAX_VALUE);

在這裏插入圖片描述

  • shutdown:
    每個任務正常運行直到結束,池關閉後不再允許有新任務被執行並拋出RejectedExecutionException異常。

  • shutdownNow結合isInterrupted() ==true 判斷:
    立即停止當前正在執行的任務,池關閉後不再允許有新任務被執行並拋出RejectedExecutionException異常。

  • shutdownNow未結合isInterrupted() ==true 判斷:
    每個任務正常運行直到結束,池關閉後不再允許有新任務被執行並拋出RejectedExecut ionException異常。

11.

方法
isTerminating()isTerminated()
使用
public class Demo2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < Integer.MAX_VALUE / 100; i++) {
                    String newString = new String();
                    Math.random();
                    Math.random();
                    Math.random();
                    Math.random();
                    Math.random();
                    Math.random();
                }
            }
        };
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<?> submit = pool.submit(runnable);
        Thread.sleep(500);
        System.out.println("A=" + pool.isTerminating());
        pool.shutdown();
        System.out.println("B=" + pool.isTerminating());
        System.out.println(submit.get());
        Thread.sleep(1000);
        System.out.println("C=" + pool.isTerminated());
    }
}

shutdown()方法關閉池之前,isTerminating()方法的返回值一直是false。
在這裏插入圖片描述

public class Demo2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < Integer.MAX_VALUE / 100; i++) {
                    String newString = new String();
                    Math.random();
                    Math.random();
                    Math.random();
                    Math.random();
                    Math.random();
                    Math.random();
                }
            }
        };
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<?> submit = pool.submit(runnable);
        Thread.sleep(500);
        System.out.println("A=" + pool.isTerminating());
        pool.shutdownNow();
        System.out.println("B=" + pool.isTerminating());
        System.out.println(submit.get());
        Thread.sleep(1000);
        System.out.println("C=" + pool.isTerminated());
    }
}

注意:在控制檯輸出了一個java.util.concurrent.CancellationException異常信息,說明先調用shutdown(),再調用get() 方法不出現異常,而先調用shutdownNow(),再調用get()方法出現異常CancellationException,說明方法shutdown()與shutdownNow()在對get()方法的處理行爲上是不一樣的。
在這裏插入圖片描述

public class Demo2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < Integer.MAX_VALUE / 100; i++) {
                    String newString = new String();
                    Math.random();
                    Math.random();
                    Math.random();
                    Math.random();
                    Math.random();
                    Math.random();
                }
            }
        };
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<?> submit = pool.submit(runnable);
        Thread.sleep(500);
        System.out.println("A=" + pool.isTerminating());
        pool.shutdownNow();
        System.out.println("B=" + pool.isTerminating());
        Thread.sleep(30000);
        System.out.println("C=" + pool.isTerminated());
    }
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章