Java多线程之-----实现自己的ThreadFactory

来源:互联网 发布:淘宝开店在哪里注册 编辑:程序博客网 时间:2024/05/19 10:36

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

在面向对象编程的世界中,工厂模式(factory pattern)是一个被广泛使用的设计模式。它是一个创建模式,它的目的是开发一个类,这个类的使命是创建一个或多个类的对象。然后,当我们要创建一个类的一个对象时,我们使用这个工厂而不是使用new操作。

  • 使用这个工厂,我们集中对象的创建,获取容易改变创建对象的类的优势,或我们创建这些对象的方式,容易限制创建对象的有限资源。比如,我们只能有一个类型的N个对象,就很容易产生关于对象创建的统计数据。

Java提供ThreadFactory接口,用来实现一个Thread对象工厂。Java并发API的一些高级工具,如执行者框架(Executor framework)或Fork/Join框架(Fork/Join framework),使用线程工厂创建线程。

在Java并发API中的其他工厂模式的例子是Executors类。它提供许多方法来创建不同类型的Executor对象。

在这个指南中,你将继承Thread类,以添加新功能,并且你将实现一个线程工厂来创建这个新类的线程。

准备工作…

这个指南的例子使用Eclipse IDE实现。如果你使用Eclipse或其他IDE,如NetBeans,打开它并创建一个新的Java项目。

如何做…

按以下步骤来实现的这个例子:

1.创建一个继承Thread类的MyThread类。

1public classMyThread extends Thread {

2.声明3个私有的、Date类型的属性:creationDate、startDate和finishDate。

1private Date creationDate;
2private Date startDate;
3private Date finishDate;

3.实现这个类的构造器。它接收名称和要执行的Runnable对象参数。存储线程的创建日期。

1public MyThread(Runnable target, String name ){
2super(target,name);
3setCreationDate();
4}

4.实现run()方法。存储线程的开始时间,调用父类的run()方法,存储执行的结束时间。

1method of the parent class, and store the finish date of the execution.
2@Override
3public voidrun() {
4setStartDate();
5super.run();
6setFinishDate();
7}

5.实现一个方法用来设置creationDate属性值。

1public voidsetCreationDate() {
2creationDate=newDate();
3}

6.实现一个方法用来设置startDate属性值。

1public voidsetStartDate() {
2startDate=newDate();
3}

7.实现一个方法用来设置finishDate属性值。

1public voidsetFinishDate() {
2finishDate=newDate();
3}

8.实现getExecutionTime()方法,用来计算线程的执行时间(结束日期与开始日期之差)。

1public longgetExecutionTime() {
2return finishDate.getTime()-startDate.getTime();
3}

9.覆盖toString()方法,返回线程的创建日期和执行日期。

01@Override
02public String toString(){
03StringBuilder buffer=newStringBuilder();
04buffer.append(getName());
05buffer.append(": ");
06buffer.append(" Creation Date: ");
07buffer.append(creationDate);
08buffer.append(" : Running time: ");
09buffer.append(getExecutionTime());
10buffer.append(" Milliseconds.");
11return buffer.toString();
12}

10.创建一个实现ThreadFactory接口的MyThreadFactory类。

1public classMyThreadFactory implementsThreadFactory {

11.声明一个私有的、int类型的属性counter。

1private intcounter;

12.声明一个私有的、String类型的属性prefix。

1private String prefix;

13.实现这个类的构造器,初始化它的属性。

1public MyThreadFactory (String prefix) {
2this.prefix=prefix;
3counter=1;
4}

14.实现newThread()方法。创建一个MyThread对象并增加counter属性值。

1@Override
2public Thread newThread(Runnable r) {
3MyThread myThread=newMyThread(r,prefix+"-"+counter);
4counter++;
5return myThread;
6}

15.创建一个实现Runnable接口的MyTask类。实现run()方法,令当前线程睡眠2秒。

01public classMyTask implements Runnable {
02@Override
03public voidrun() {
04try {
05TimeUnit.SECONDS.sleep(2);
06} catch(InterruptedException e) {
07e.printStackTrace();
08}
09}
10}

16.实现这个例子的主类,通过创建Main类,并实现main()方法。

1public classMain {
2public staticvoid main(String[] args) throws Exception {

17.创建一个MyThreadFactory对象。

1MyThreadFactory myFactory=newMyThreadFactory("MyThreadFactory");

18.创建一个Task对象。

1MyTask task=newMyTask();

19.使用这个工厂的newThread()方法,创建一个MyThread对象来执行任务。

1Thread thread=myFactory.newThread(task);

20.启动这个线程并等待它的结束。

1thread.start();
2thread.join();

21.使用toString()方法,写入关于线程的信息。

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

它是如何工作的…

在这个指南中,你已经通过继承Thread类来实现自定义的MyThread类。这个类有3个属性用来存储:创建日期、执行的开始日期和执行的结束日期。你已实现getExecutionTime()方法,使用开始日期和结束日期属性,返回线程已执行任务的时间。最后,你已覆盖toString()方法来产生关于线程的信息。

一旦你有自己的线程类,你已实现一个工厂来创建这个实现了ThreadFactory接口的类的对象。如果你要使用你的工厂作为一个独立的对象,这个接口的使用并不是强制的,但是如果你想要用这个工厂使用Java并发API的其他类,你必须通过实现这个接口来构建你的工厂。ThreadFactory接口只有一个方法,newThread()方法接收一个Runnable对象作为参数,并且返回一个用来执行Runnable对象的Thread对象。在你的例子中,你返回一个MyThread对象。

检查这两个类,你已实现MyTask类,这个类实现了Runnable对象。这是将在由MyThread对象管理的线程中执行的任务。一个MyTask实例令它的执行线程睡眠2秒。

在这个例子的主方法中,你已使用MyThreadFactory工厂创建一个MyThread对象,用来执行一个Task对象。执行这个程序,你将看到一条关于开始日期和线程执行的执行时间的信息。

以下截图显示这个例子产生的输出:

2

不止这些…

Java并发API提供Executors类来产生线程执行者,通常是ThreadPoolExecutor类的对象。你也可以使用defaultThreadFactory()方法,让这个类来获取ThreadFactory接口最基本的实现。这个方法产生的工厂所产生的基本Thread对象都属性同一个ThreadGroup对象。

你可以在你的程序中使用ThreadFactory接口用于任何目的,不一定要与执行者框架(Executor framework)有关。




  1. package com.bird.concursey;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Date;  
  5. import java.util.Iterator;  
  6. import java.util.List;  
  7. import java.util.concurrent.ThreadFactory;  
  8.   
  9. public class MyThreadFactory implements ThreadFactory {  
  10.       
  11.     private int counter;  
  12.     private String name;  
  13.     private List<String> stats;  
  14.       
  15.     public MyThreadFactory(String name) {  
  16.         counter = 0;  
  17.         this.name = name;  
  18.         stats = new ArrayList<String>();  
  19.     }  
  20.   
  21.     @Override  
  22.     public Thread newThread(Runnable run) {  
  23.         Thread t = new Thread(run, name + "-Thread-" + counter);  
  24.         counter++;  
  25.         stats.add(String.format("Created thread %d with name %s on%s\n" ,t.getId() ,t.getName() ,new Date()));  
  26.         return t;  
  27.     }  
  28.       
  29.     public String getStas() {  
  30.         StringBuffer buffer = new StringBuffer();  
  31.         Iterator<String> it = stats.iterator();  
  32.         while(it.hasNext()) {  
  33.             buffer.append(it.next());  
  34.             buffer.append("\n");  
  35.         }  
  36.         return buffer.toString();  
  37.     }  
  38.       
  39.     public static void main(String[] args) {  
  40.         MyThreadFactory factory = new MyThreadFactory("MyThreadFactory");  
  41.         Task task = new Task();  
  42.         Thread thread = null;  
  43.         for(int i = 0; i < 10; i++) {  
  44.             thread = factory.newThread(task);  
  45.             thread.start();  
  46.         }  
  47.         System.out.printf("Factory stats:\n");  
  48.         System.out.printf("%s\n",factory.getStas());  
  49.           
  50.           
  51.     }  
  52.   


0 0
原创粉丝点击