监控执行器框架

Java 9并发编程指南 目录

Executor框架将任务实现与线程创建和执行任务的管理分离开来。 如果使用执行器,只需要实现Runnable对象,然后发送到执行器即可。管理线程是执行器的责任,当向执行器发送任务时,它尝试使用池线程来执行任务,以避免创建新线程。这种机制由Executor接口及其实现类作为ThreadPoolExecutor类提供。

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

准备工作

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

实现过程

通过如下步骤实现范例:

  1. 创建名为Task的类,实现Runnable接口:

    public class Task implements Runnable{
    
  2. 声明名为milliseconds的私有long属性:

    	private final long milliseconds;
    
  3. 实现类构造函数,初始化属性:

    	public Task (long milliseconds) {
    		this.milliseconds=milliseconds;
    	}
    
  4. 实现run()方法,设置线程休眠为milliseconds属性指定的毫秒数:

    	@Override
    	public void run() {
    		System.out.printf("%s: Begin\n", Thread.currentThread().getName());
    		try {
    			TimeUnit.MILLISECONDS.sleep(milliseconds);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.printf("%s: End\n", Thread.currentThread().getName());
    	}
    }
    
  5. 实现本范例主类,创建名为Main的类,包含main()方法:

    public class Main {
    	public static void main(String[] args) throws Exception{
    
  6. 使用Executors类的newCachedThreadPool()方法创建新的Executor对象:

    		ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
    
  7. 创建和提交10个Task对象到执行器,使用随机数初始化这些对象:

    		Random random=new Random();
    		for (int i=0; i<10; i++) {
    			Task task=new Task(random.nextInt(10000));
    			executor.submit(task);
    		}
    
  8. 创建重复五次的循环,每次循环中,通过调用showLog()方法输出执行器信息到控制台,并设置线程休眠1秒钟:

    		for (int i=0; i<5; i++){
    			showLog(executor);
    			TimeUnit.SECONDS.sleep(1);
    		}
    
  9. 使用shutdown()方法关闭执行器:

    		executor.shutdown();
    
  10. 创建重复五次的循环,每次循环中,通过调用showLog()方法输出执行器信息到控制台,并设置线程休眠1秒钟:

    		for (int i=0; i<5; i++){
    			showLog(executor);
    			TimeUnit.SECONDS.sleep(1);
    		}
    
  11. 使用awaitTermination()方法等待执行器结束:

    		executor.awaitTermination(1, TimeUnit.DAYS);
    
  12. 输出指明程序结束的信息到控制台:

    		System.out.printf("Main: End of the program.\n");
    	}
    
  13. 实现showLog()方法,将Executor作为参数接收。输出池大小、任务数量和执行器状态信息到控制台:

    	private static void showLog(ThreadPoolExecutor executor) {
    		System.out.printf("*********************");
    		System.out.printf("Main: Executor Log");
    		System.out.printf("Main: Executor: Core Pool Size: %d\n", executor.getCorePoolSize());
    		System.out.printf("Main: Executor: Pool Size: %d\n", executor.getPoolSize());
    		System.out.printf("Main: Executor: Active Count: %d\n", executor.getActiveCount());
    		System.out.printf("Main: Executor: Task Count: %d\n", executor.getTaskCount());
    		System.out.printf("Main: Executor: Completed Task Count: %d\n", executor.getCompletedTaskCount());
    		System.out.printf("Main: Executor: Shutdown: %s\n", executor.isShutdown());
    		System.out.printf("Main: Executor: Terminating: %s\n", executor.isTerminating());
    		System.out.printf("Main: Executor: Terminated: %s\n", executor.isTerminated());
    		System.out.printf("*********************\n");
    	}
    }
    

工作原理

本节,实现了阻塞执行线程随机毫秒数的任务。然后发送10个任务到执行器,且当等待任务结束时,输出执行器状态信息到控制台。使用如下方法得到Executor对象的状态:

  • getCorePoolSize():返回整型数字,表示线程的核心数量。当执行器不执行任何任务时,它是在内部线程池中的最小线程数。
  • getPoolSize():返回整型数字,表示内部线程池的实际大小。
  • getActiveCount():返回整型数字,表示当前执行任务的线程数量。
  • getTaskCount():返回长整型数字,表示计划执行的任务数量。
  • getCompletedTaskCount():返回长整型数字,表示执行器已经执行且完成执行的任务数量。
  • isShutdown():当调用执行器的shutdown()方法结束执行时,返回Boolean值。
  • isTerminating():当执行器运行shutdown()操作但尚未结束时,返回Boolean值。
  • isTerminated():当执行器结束执行时,返回Boolean值。

更多关注

  • 第四章“线程执行器”中的“创建线程执行器并控制其被拒任务”小节
  • 第八章“定制并发类”中的“定制ThreadPoolExecutor类”和“实现基于优先级的执行器类”小节

猜你喜欢

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