用线程池执行任务

如果你开发项目的时候用到很多的short-lived任务,这里推荐使用“线程池”这项技术。你可以创建一个线程池来执行池中的的任务,来取代每次执行任务是都要为新的任务来new和discard。如果一个线程在池中是可用状态,那么任务将立即执行。执行完成之后线程返回池中,否则,任务将一直等待直到有线程处在可用状态。
   
    J2SE 5.0为大家提供了一个新的java.util.concurrent package,并且在这个报中提供了一个pre-built 的线程池架构。在java.util.concurrent中提供了一个Executor 接口,里面有一个execute的方法,参数是Runnable 类型
   public interface Executor {
     public void execute(Runnable command);
   }


   使用线程池架构,你就必须创建一个Executor实例,然后你给他分配一些runnable任务,例如:
   Executor executor = ...;
   executor.execute(aRunnable1);
   executor.execute(aRunnable2);


    然后你创建或者找到Executor的实现类,实现类可以立即(或者连续)执行分配的任务,例如:
   class MyExecutor implements Executor {
       public void execute(Runnable r) {
           new Thread(r).start();
       }
   }

    concurrency utilities也包括了一个ThreadPoolExecutor类,它提供了很多对线程的一般性操作,提供了四个构造函数,每个都可以指定如:线程池大小,持续时间,一个线程factory,和拒绝线程的handler。
   public ThreadPoolExecutor(int corePoolSize,
                             int maximumPoolSize,
                             long keepAliveTime,
                             TimeUnit unit,
                             BlockingQueue<Runnable> workQueue)
   public ThreadPoolExecutor(int corePoolSize,
                             int maximumPoolSize,
                             long keepAliveTime,
                             TimeUnit unit,
                             BlockingQueue<Runnable> workQueue,
                             ThreadFactory threadFactory)
   public ThreadPoolExecutor(int corePoolSize,
                             int maximumPoolSize,
                             long keepAliveTime,
                             TimeUnit unit,
                             BlockingQueue<Runnable> workQueue,
                             RejectedExecutionHandler handler)
   public ThreadPoolExecutor(int corePoolSize,
                             int maximumPoolSize,
                             long keepAliveTime,
                             TimeUnit unit,
                             BlockingQueue<Runnable> workQueue,
                             ThreadFactory threadFactory,
                             RejectedExecutionHandler handler)

     但是你不必声明构造函数,Executors类会为你创建一个线程池。在一种最简单的情况下,你在Executors类中声明了newFixedThreadPool方法,并且在池中分配了许多线程。你可以使用ExecutorService(继承Executor的一个接口),去execute和submit 那些Runnable任务,使用ExecutorService中的submit方法可以得到一个返回结果,当然submit也可以返回一个Future对象用来检查任务是否执行。

      让我们来先做一个Runnable类,名字为NamePrinter,它通知你运行、暂停、和耗费的时间。
   public class NamePrinter implements Runnable {
     private final String name;
     private final int delay;
     public NamePrinter(String name, int delay) {
       this.name = name;
       this.delay = delay;
     }
     public void run() {
       System.out.println("Starting: " + name);
       try {
         Thread.sleep(delay);
       } catch (InterruptedException ignored) {
       }
       System.out.println("Done with: " + name);
     }
   }


    然后下面是我们测试的项目UsePool,它创建一个有三个线程的线程池,分配了10个任务给它(运行10次NamePrinter),UsePool在被shutdown 和 awaitTermination之前将等待并执行分配的任务。一个ExecutorService必须要在terminated之前执行shutdown,shutdownNow方法是立即尝试shutdown操作。shutdownNow 方法将返回没有被执行的任务。

   import java.util.concurrent.*;
   import java.util.Random;
   
   
   public class UsePool {
     public static void main(String args[]) {
       Random random = new Random();
       ExecutorService executor = 
               Executors.newFixedThreadPool(3);
       // Sum up wait times to know when to shutdown
       int waitTime = 500;
       for (int i=0; i<10; i++) {
         String name = "NamePrinter " + i;
         int time = random.nextInt(1000);
         waitTime += time;
         Runnable runner = new NamePrinter(name, time);
         System.out.println("Adding: " + name + " / " + time);
         executor.execute(runner);
       }
       try {
         Thread.sleep(waitTime);
         executor.shutdown();
         executor.awaitTermination
                 (waitTime, TimeUnit.MILLISECONDS);
       } catch (InterruptedException ignored) {
       }
       System.exit(0);
     }
    }


    输出的结果是:
   Adding: NamePrinter 0 / 30
   Adding: NamePrinter 1 / 727
   Adding: NamePrinter 2 / 980
   Starting: NamePrinter 0
   Starting: NamePrinter 1
   Starting: NamePrinter 2
   Adding: NamePrinter 3 / 409
   Adding: NamePrinter 4 / 49
   Adding: NamePrinter 5 / 802
   Adding: NamePrinter 6 / 211
   Adding: NamePrinter 7 / 459
   Adding: NamePrinter 8 / 994
   Adding: NamePrinter 9 / 459  
   Done with: NamePrinter 0
   Starting: NamePrinter 3
   Done with: NamePrinter 3
   Starting: NamePrinter 4
   Done with: NamePrinter 4
   Starting: NamePrinter 5
   Done with: NamePrinter 1
   Starting: NamePrinter 6
   Done with: NamePrinter 6
   Starting: NamePrinter 7
   Done with: NamePrinter 2
   Starting: NamePrinter 8
   Done with: NamePrinter 5
   Starting: NamePrinter 9
   Done with: NamePrinter 7
   Done with: NamePrinter 9
   Done with: NamePrinter 8

   注意前三个NamePrinter对象启动的非查的快,之后的NamePrinter对象每次启动都要等待前面的执行完成。

    在J2SE 5.0有非常多的pooling framework可以用,例如,你可以创建一个scheduled线程池……
    更多信息还是看官方的concurrency utilities,地址:http://java.sun.com/j2se/1.5.0/docs/guide/concurrency/

你可能感兴趣的:(thread,J2SE,UP,sun)