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