12.
方法
public boolean isShutdown()
的使用
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("打印了!begin " + Thread.currentThread().getName());
Thread.sleep(1000);
System.out.println("打印了!end" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ForkJoinPool pool = new ForkJoinPool();
pool.execute(runnable);
System.out.println("A=" + pool.isShutdown());
pool.shutdown();
Thread.sleep(5000);
System.out.println("B=" + pool.isShutdown());
}
}
任务成功被运行。
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("打印了!begin " + Thread.currentThread().getName());
Thread.sleep(1000);
System.out.println("打印了!end" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ForkJoinPool pool = new ForkJoinPool();
pool.execute(runnable);
System.out.println("A=" + pool.isShutdown());
pool.shutdownNow();
Thread.sleep(5000);
System.out.println("B=" + pool.isShutdown());
}
}
任务成功被运行,由于shutdownNow()方法在源代码内部使用了interrupt() 方法,所以interrupt()方法遇到sleep()抛出“ java.lang.InterruptedException: sleep interrupted”异常。
如果使用Callable接口,则需要使用Future对象的get()方法获得异常。
13.
方法
public boolean awaitTermination(long timeout, TimeUnit unit)
的使用
方法awaitTermination(long timeout, TimeUnit unit)的作用是等待池被销毁的最长时间,具有阻塞特性。
public class Demo4 {
public static void main(String[] args) throws InterruptedException {
Runnable_a a = new Runnable_a();
ForkJoinPool pool = new ForkJoinPool();
pool.execute(a);
System.out.println("main begin! " + System.currentTimeMillis());
//awaitTermination具有阻塞特性
System.out.println(pool.awaitTermination(10, TimeUnit.SECONDS));
System.out.println("main end! " + System.currentTimeMillis());
}
}
class Runnable_a 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();
}
}
}
class Runnable_b implements Runnable {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
返回值打印false,说明任务池并没有被销毁。
日志main begin和main end之间的时差差4秒,返回值打印true,代表任务池在4秒后.被销毁,所以awaitTermination(long timeout, TimeUnit unit)要结合shutdown()方法进行使用。
14.
方法
public <T> T invoke(ForkJoinTask<T> task)
的使用
public class Demo5 {
public static void main(String[] args) {
RecursiveAction_ action = new RecursiveAction_();
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(action);
}
}
class RecursiveAction_ extends RecursiveAction {
@Override
protected void compute() {
System.out.println("TheadName=" + Thread.currentThread().getName());
}
}
class RecursiveTask_ extends RecursiveTask<String> {
@Override
protected String compute() {
return "我是返回值";
}
}
方法execute(task)、submit(task) 以及invoke(task) 都可以在异步队列中执行任务,需要注意的是,方法invoke()是阻塞的
,而它们在使用上的区别其实很简单:
- execute(task) 只执行任务,没有返回值
- 而submit(task)方法有返回值,返回值类型是ForkJoinTask, 想取得返回值时,需要使用ForkJoinTask对象的get() 方法
- 而invoke(task)和submit(task)方法一样都具有返回值的功能,区别就是invoke(task)方法直接将返回值进行返回,而不是通过ForkJoinTask对象的get(方法。
这3个方法的声明如下:
pool.execute(task);
//pulic void execute(ForkJoinTask<?> task)
pool.submit(task);
//public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task)
pool.invoke(task);
//public <T> T invoke(ForkJoinTask<T> task)
15. 监视pool池的状态
- 方法
getParallelism()
:获得并行的数量,与CPU的内核数有关; - 方法
getPoolSize()
:获得任务池的大小; - 方法
getQueuedSubmissionCount()
:取得已经提交但尚未被执行的任务数量; - 方法
hasQueuedSubmissions()
:判断队列中是否有未执行的任务; - 方法
getActiveThreadCount()
:获得活动的线程个数; - 方法
getQueuedTaskCount()
:获得任务的总个数; - 方法
getStealCount()
:获得偷窃的任务个数; - 方法
getRunningThreadCount()
:获得正在运行并且不在阻塞状态下的线程个数; - 方法
isQuiescent()
:判断任务池是否是静止未执行任务的状态。
public class Demo6 {
public static void main(String[] args) {
MyRecursiveTask_1 task_1 = new MyRecursiveTask_1();
MyRecursiveTask_1 task_2 = new MyRecursiveTask_1();
MyRecursiveTask_1 task_3 = new MyRecursiveTask_1();
ForkJoinPool pool = new ForkJoinPool();
pool.submit(task_1);
pool.submit(task_2);
pool.submit(task_3);
System.out.println("并行数getParallelism()=" + pool.getParallelism());
System.out.println("线程池大小getPoolSize()=" + pool.getPoolSize());
do {
}while (!pool.isTerminated());
System.out.println("main end");
}
}
class MyRecursiveTask_1 extends RecursiveAction {
@Override
protected void compute() {
try {
System.out.println("begin=" + Thread.currentThread().getName());
Thread.sleep(1000);
System.out.println("end=" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ForkJoinTask对异常的处理
- 方法
isCompletedAbnormally()
判断任务是否出现异常 - 方法
isCompletedNormally()
判断任务是否正常执行完毕 - 方法
getException()
返回报错异常
public class Demo7 {
public static void main(String[] args) throws InterruptedException {
MyRecursiveTaskX taskX = new MyRecursiveTaskX();
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Integer> submit = pool.submit(taskX);
System.out.println(submit.isCompletedAbnormally() + " " + submit.isCompletedNormally());
Thread.sleep(2000);
System.out.println(submit.isCompletedAbnormally() + " " + submit.isCompletedNormally());
System.out.println(submit.getException());
}
}
class MyRecursiveTaskX extends RecursiveTask<Integer> {
@Override
protected Integer compute() {
try {
Thread.sleep(1000);
Integer.parseInt("a");
} catch (NumberFormatException e) {
e.printStackTrace();
//需要抛出NumberFromatException异常,MyRecursiveTaskX对象从而可以获得任务执行的结果的情况
throw e;
} catch (InterruptedException e) {
e.printStackTrace();
}
return 100;
}
}