实现ThreadFactory接口生成自定义线程

Java 9并发编程指南 目录

实现ThreadFactory接口生成自定义线程

在面向对象编程领域中,工厂模式是广泛使用的设计模式,创造性的通过开发类来创建一个或多个类的对象。当想要创建其中一个类的对象时,我们使用工厂来代替新的操作符。

考虑到在创建具有有限资源的对象时所遇到的限制,在工厂模式中将对对象创建集中化,因此在更改创建的对象类或者对象方式上更有优势。例如,只有一个类型的N个对象,就能够轻松地生成关于对象创建的统计数据。

Java提供ThreadFactory接口来实现Thread对象工厂。Java并发API中一些高级功能,例如fork/join的Executor框架,就使用线程工厂创建线程。Java并发API中里一个工厂模式的例子是Executors类,它提供了大量创建不同类别的Executor对象的方法。本节将通过继承Thread类添加新功能,实现一个新的线程工厂类来生成线程。

准备工作

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

实现过程

通过如下步骤实现范例:

  1. 创建名为MyThread的类,继承Thread类:

    public class MyThread extends Thread{
    
  2. 声明名为creationDate、startDate和finishDate三个私有Date属性:

    	private final Date creationDate;
    	private Date startDate;
    	private Date finishDate;
    
  3. 实现类构造函数,将name和待执行的Runnable对象作为参数接收。初始化线程的创建时间:

    	public MyThread(Runnable target, String name ){
    		super(target,name);
    		creationDate = new Date();
    	}
    
  4. 实现run()方法,存储线程的起始时间,调用父类的run()方法,存储执行的结束时间:

    	@Override
    	public void run() {
    		setStartDate();
    		super.run();
    		setFinishDate();
    	}
    
  5. 实现建立startDate属性值的方法:

    	public synchronized void setStartDate() {
    		startDate=new Date();
    	}
    
  6. 实现建立finishDate属性值的方法:

    	public synchronized void setFinishDate() {
    		finishDate=new Date();
    	}
    
  7. 实现名为getExecutionTime()的方法,通过完成时间与开始时间的差值来计算线程的执行时间:

    	public synchronized long getExecutionTime() {
    		return finishDate.getTime()-startDate.getTime();
    	}
    
  8. 重写toString()方法,返回线程的创建时间和执行时间:

    	@Override
    	public synchronized String toString(){
    		StringBuilder buffer=new StringBuilder();
    		buffer.append(getName());
    		buffer.append(": ");
    		buffer.append(" Creation Date: ");
    		buffer.append(creationDate);
    		buffer.append(" : Running time: ");
    		buffer.append(getExecutionTime());
    		buffer.append(" Milliseconds.");
    		return buffer.toString();
    	}
    }
    
  9. 创建名为MyThreadFactory的类,实现ThreadFactory接口:

    public class MyThreadFactory implements ThreadFactory{
    
  10. 声明名为counter的私有AtomicInteger属性:

    	private AtomicInteger counter;
    
  11. 声明名为prefix的私有String属性:

    	private String prefix;
    
  12. 实现类构造函数,初始化属性:

    	public MyThreadFactory (String prefix) {
    		this.prefix=prefix;
    		counter=new AtomicInteger(1);
    	}
    
  13. 实现newThread()方法,创建MyThread对象且递增counter属性:

    	@Override
    	public Thread newThread(Runnable r) {
    		MyThread myThread=new MyThread(r,prefix+"-"+counter.getAndIncrement());
    		return myThread;
    	}
    }
    
  14. 创建名为MyTask的类来实现Runnable接口,实现run()方法,设置当前线程休眠2秒钟:

    public class MyTask implements Runnable{
    	@Override
    	public void run() {
    		try {
    			TimeUnit.SECONDS.sleep(2);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
  15. 通过创建名为Main的类,添加main()方法,实现本范例主类:

    public class Main {
    	public static void main(String[] args) throws Exception {
    
  16. 创建MyThreadFactory对象:

    		MyThreadFactory myFactory=new MyThreadFactory("MyThreadFactory");
    
  17. 创建Task对象:

    		MyTask task=new MyTask();
    
  18. 使用工厂的newThread()方法创建MyThread对象,用来执行任务:

    		Thread thread=myFactory.newThread(task);
    
  19. 启动线程,然后等待线程结束:

    		thread.start();
    		thread.join();
    
  20. 使用toString()方法输出线程信息到控制台:

    		System.out.printf("Main: Thread information.\n");
    		System.out.printf("%s\n",thread);
    		System.out.printf("Main: End of the example.\n");
    	}
    }
    

工作原理

本节通过继承Thread类实现了定制化的Mythread类。此类包含三个属性,分别存储线程创建和执行的开始时间,以及线程执行的结束时间。使用开始和结束时间属性,实现了getExecutionTime()方法,返回线程在执行任务时消耗的总时间。最后,重写toString()方法生成线程相关信息。

一旦线程类自定义后,就通过实现ThreadFactory接口生成一个工厂来创建类对象。如果要将工厂作为独立对象,则不需要强制使用此接口,但是如果要将此工厂与Java并发API的其他类一起使用,则必须通过实现此接口来构建工厂。ThreadFactory接口只有一个方法:newThread()方法。此方法将Runnble对象作为参数接收,并返回Thread对象来执行Runnable对象。本范例中返回MyThread对象。

为了检查这两个类,实现MyTask类,在MyThread对象管理的线程中执行的任务 ,此类实现Runnable接口。一个MyTask实例设置其执行线程休眠2秒钟。

在本范例主方法中,使用执行Task对象的MyThreadFactory工厂来创建MyThread对象。如果执行本范例,将会看到线程启动时间和线程执行时间的信息。

下图显示本范例在控制台输出的执行信息:

pics/08_02.jpg

扩展学习

Java并发API提供Executors类来生成线程执行器,通常是ThreadPoolExecutor类的对象。还可以使用此类获得ThreadFactory接口的最基本实现,通过使用defaultThreadFactory()方法。此方法生成的工厂创建属于同一个ThreadGroup对象的基本线程对象,ThreadFactory接口可以用于任何目的,不只是与Executor框架相关。

猜你喜欢

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