站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Java 专题使用线程池处理简短任务

使用线程池处理简短任务

摘要: 使用线程池处理简短任务

</td> </tr> <tr> <td height="35" valign="top" class="ArticleTeitle"> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="405" height="86" align="left" valign="top">


当java程序中要用线程处理多个简短任务的时候,使用一种叫做Thread Pooling的技术是很明智的选择。为了不对单个任务逐个创建(并在任务结束时结束)线程,过去我们经常自己编写适合不同运行环境需要的线程池。虽然这些线程池的具体属性参数不尽相同,但是大致都追寻着如下的应用套式:

把任务组引入到线程池里面,
如果线程池中某个线程满足执行条件,立刻执行
任务执行完毕,线程返回线程池
不满足执行条件(比如线程池大小条件),等待执行

J2SE5.0现在提供了全新的java.util.concurrent包,其中有几经构建好的线程池的框架。

例如:Executor接口提供了单独的一个办法execute来接收一个Runnable的实例对象:
public interface Executor {
public void execute(Runnable command);
}

</td> <td width="279" valign="top"> </td> </tr> </table>

所以我们可以创建一个Executor对象 然后把runnable任务引入:

Executor executor = ...; //可以完成implements后创建...
executor.execute(aRunnable1);
executor.execute(aRunnable2);

例如:

class MyExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}
}

在concurrency中还包括一个ThreadPoolExecutor类来提供一般通用用途的线程池操作.下面是4种该类的构造器.我们可以确定该类的某些属性例如: 池的大小,活动时间,线程工厂和被拒绝运行线程控制器.

  public ThreadPoolExecutor(int corePoolSize,

                             int maximumPoolSize,

                             long keepAliveTime,

                             TimeUnit unit,

                             BlockingQueue workQueue)

   public ThreadPoolExecutor(int corePoolSize,

                             int maximumPoolSize,

                             long keepAliveTime,

                             TimeUnit unit,

                             BlockingQueue workQueue,

                             ThreadFactory threadFactory)

   public ThreadPoolExecutor(int corePoolSize,

                             int maximumPoolSize,

                             long keepAliveTime,

                             TimeUnit unit,

                             BlockingQueue workQueue,

                             RejectedExecutionHandler handler)

   public ThreadPoolExecutor(int corePoolSize,

                             int maximumPoolSize,

                             long keepAliveTime,

                             TimeUnit unit,

                             BlockingQueue workQueue,

                             ThreadFactory threadFactory,

                             RejectedExecutionHandler handler)


其实我们实际使用线程池的时候并不需要用构造器来专门建立上面的ThreadPoolExecutor的对象.Executors类中已经创建了默认的线程池.例如我们可以在Executors中调用newFixedThreadPool办法规定你需要的线程池的大小.可以使用一个继承了Executor的ExectuorService类来运行或者提交Runnalbe任务组. ExectuorService的提交办法 -- submit 允许得到一个结果F, 而且返回FUTURE OBJECT,可以用来检查是否任务已经执行完毕.
下面是一个具体的应用实例: -- 摘自sun技术论坛
  

     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);

     }

   }

----------------------------------------------------------------------------------

   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); //设定线程池容量为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);

     }

    }

----------------------------------------------------------------------------------

可能输出:

unique with the random sleeps present:

   Adding: NamePrinter 0 / 30

   Adding: NamePrinter 1 / 727

   Adding: NamePrinter 2 / 980  //前3个添加进行的明显比较快

   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     但是因为线程池容量为3个,

   Done with: NamePrinter 3    前3个任务又都在执行,

   Starting: NamePrinter 4     所以任务3一直等到任务0结束才开始执行

   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


线程池框架中还有很多其它的内容,请参考api. _ </td> </tr> <tr>


↑返回目录
前一篇: Swing中的getContentPane()方法
后一篇: 如何保护Java程序