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());
}
}