监控fork/join池

Java 9并发编程指南 目录

Executor框架将任务实现与线程创建和执行任务的管理分离开来。Java提供的fork/join框架扩展了执行器框架,用于解决特定类型的问题,以提高其它解决方案(直接使用Thread对象或者执行器框架)的性能。

fork/join框架旨在解决使用fork()和join()操作能够分解为更小任务的问题。实现此特性的主类是ForkJoinPool。

本节将学习关于ForkJoinPool执行器的状态信息,以及如何获取这些信息。

准备工作

本范例通过Eclipse开发工具实现。如果使用诸如NetBeans的开发工具,打开并创建一个新的Java项目。

实现过程

通过如下步骤实现范例:

  1. 创建名为Task的类,继承RecursiveAction类:

    public class Task extends RecursiveAction{
    
  2. 声明名为array的私有int数组属性,存储待增加的元素数组:

    	private final int array[];
    
  3. 声明名为start和end的两个私有int属性,存储需要处理的任务元素块的开始和结束位置:

    	private final int start;
    	private final int end;
    
  4. 实现类构造函数,初始化属性:

    	public Task (int array[], int start, int end) {
    		this.array=array;
    		this.start=start;
    		this.end=end;
    	}
    
  5. 实现compute()方法,包含任务的主要逻辑。如果任务需要处理超过100个元素,首先将元素拆分成两部分,创建两个任务分别执行每部分,使用fork()方法开始执行任务,最后使用join()方法等待任务结束:

    	@Override
    	protected void compute() {
    		if (end-start>100) {
    			int mid=(start+end)/2;
    			Task task1=new Task(array,start,mid);
    			Task task2=new Task(array,mid,end);
    			task1.fork();
    			task2.fork();
    			task1.join();
    			task2.join();
    
  6. 否则,执行增加元素的操作,并在每次操作之后,设置线程休眠5毫秒:

    		} else {
    			for (int i=start; i<end; i++) {
    				array[i]++;
    				try {
    					Thread.sleep(5);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    }
    
  7. 实现本范例主类,创建名为Main的类,包含main()方法:

    public class Main {
    	public static void main(String[] args) throws Exception{
    
  8. 创建名为pool的ForkJoinPool对象:

    		ForkJoinPool pool=new ForkJoinPool();
    
  9. 创建名为array的整型数字数组,包含10000个元素:

    		int array[]=new int[10000];
    
  10. 创建新Task对象,处理整个数组:

    		Task task1=new Task(array,0,array.length);
    
  11. 使用execute()犯法发送执行任务到池中:

    		pool.execute(task1);
    
  12. 如果任务尚未执行结束,调用showLog()方法输出ForkJoinPool类状态信息到控制台,然后设置线程休眠1秒钟:

    		while (!task1.isDone()) {
    			showLog(pool);
    			TimeUnit.SECONDS.sleep(1);
    		}
    
  13. 使用shutdown()方法关闭池:

    		pool.shutdown();
    
  14. 使用awaitTermination()等待池运行结束:

    		pool.awaitTermination(1, TimeUnit.DAYS);
    
  15. 调用showLog()方法输出ForkJoinPool类状态信息到控制台,然后输出指明程序结束的信息到控制台:

    		showLog(pool);
    		System.out.printf("Main: End of the program.\n");
    	}
    
  16. 实现showLog()方法,将ForkJoinPool对象作为参数接收,输出其状态和线程,以及正在执行的任务信息到控制台:

    	private static void showLog(ForkJoinPool pool) {
    		System.out.printf("**********************\n");
    		System.out.printf("Main: Fork/Join Pool log\n");
    		System.out.printf("Main: Fork/Join Pool: Parallelism: %d\n", pool.getParallelism());
    		System.out.printf("Main: Fork/Join Pool: Pool Size: %d\n", pool.getPoolSize());
    		System.out.printf("Main: Fork/Join Pool: Active Thread Count: %d\n", pool.getActiveThreadCount());
    		System.out.printf("Main: Fork/Join Pool: Running Thread Count: %d\n", pool.getRunningThreadCount());
    		System.out.printf("Main: Fork/Join Pool: Queued Submission: %d\n", pool.getQueuedSubmissionCount());
    		System.out.printf("Main: Fork/Join Pool: Queued Tasks: %d\n", pool.getQueuedTaskCount());
    		System.out.printf("Main: Fork/Join Pool: Queued Submissions: %s\n", pool.hasQueuedSubmissions());
    		System.out.printf("Main: Fork/Join Pool: Steal Count: %d\n", pool.getStealCount());
    		System.out.printf("Main: Fork/Join Pool: Terminated : %s\n", pool.isTerminated());
    		System.out.printf("**********************\n");
    	}
    }
    

工作原理

本节实现了递增数组元素的任务,使用到ForkJoinPool类和继承RecursiveAction类的Task类。这是能够在ForkJoinPool类中执行的任务之一,当任务处理数组时,输出ForkJoinPool类的状态信息到控制台。通过使用如下方法得到ForkJoinPool类的状态信息:

  • getPoolSize():返回ForkJoinPool类内部池的工作线程数量的int值
  • getParallelism():返回为池建立的所需的并行级别
  • getActiveThreadCount():返回当前执行任务的线程数量
  • getRunningThreadCount():返回在任何同步机制中均未阻塞的工作线程
  • getQueuedSubmissionCount():返回已经进入池中,但尚未开始执行的任务数量
  • getQueuedTaskCount():返回已经进入池中且开始执行的任务数量
  • hasQueuedSubmissions():返回Boolean值,指明池是否有尚未开始执行的队列任务的
  • getStealCount():返回long值,指定工作线程从其它线程处窃取任务的次数
  • isTerminated():返回Boolean值,指明fork/join框架是否已经完成执行

更多关注

  • 第五章“Fork/Join框架”中的“创建fork/join池”小节
  • 第八章“定制并发类”中的“实现为fork/join框架生成自定义线程的ThreadFactory接口”和“定制在fork/join框架中运行的任务”小节

猜你喜欢

转载自blog.csdn.net/nicolastsuei/article/details/84646123