多线程(六)executor和线程池

常见的线程池是fixed thread pool,即线程池中可运行的最大线程数是固定的。它使用一个内部queue来排队,当线程池中运行的线程达到上限时,其他的任务需要等待。当一个线程执行的任务(runnable)结束时,线程继续执行下一个runnable,这种方式可节约大量创建thread所消耗的资源。

继续使用上文中的例子说明如何使用executor和线程池:

        //这里注意scanner和transfer必须共享同一个对象fileArray。
       //我们希望有一个线程来扫描目录,有多个线程来传输扫描到的文件
       //首先实例化这两个类:扫描类和传输类。我们将在后面的代码中使用这两个实例来创建线程。

        FTPFileTransfer fileTransfer = new FTPFileTransfer( fileArray);
        FolderScanner folderScanner = new FolderScanner( fileArray);

private void run()  {

       //首先取得在配置文件中配置的希望在线程池中使用多少个线程数
        int threadPoolNumber = Integer.parseInt(getAppProperty("ThreadPoolNumber"));
       //使用类Executors的静态方法返回线程池。
       //Executors返回线程池的静态方法有很多,返回不同种类的线程池。不同种类的线程池实现的也是不同的executor接口。
       //executor有三种接口:Executor, ExecutorService 和 ScheduledExecutorService。

        ExecutorService pool = Executors.newFixedThreadPool(threadPoolNumber);

       //用submit放入pool中一个task。
       //这样会立即create一个线程用于运行folderScanner类中的run方法。
       //注意submit的是一个实现了runnable或callable或future的对象,
       //而不是 一个thread。这样是不对的:pool.submit(new Thread(folderScanner));
       //不使用submit提交task,则不会有线程被创建。
       //下面就创建了一个在线程池中的线程,该线程执行的是扫描目录的功能。

        pool.submit(folderScanner);

      //对于要使用多个线程的tranfer,则需要使用for循环submit足够多的task。因为有一个线程已经被用作scanner了,所以这里threadPoolNumber要减1.

        for(int i = 0; i < threadPoolNumber-1; i++){
            pool.submit(fileTransfer);
        }
        
       //这段code的作用仅仅是让main线程一直运行不退出。 
        while(!getIfStop()){
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
       //不要忘记使用完后要在主线程中shutdown线程池。
       //shutdown会等待线程都执行完毕后结束,也有方法可以实现立即结束。
       //如果不是使用线程池,而是直接创建的线程,则可以使用join等待子线程结束。
        pool.shutdown();            
    }

注意上面代码中的 pool.submit(folderScanner); 也就是说向线程池中提交的不是一个线程,而是一个对象。提交对象后,线程池会立即create 一个thread来运行folderScanner。当folderScanner运行结束后,该thread被复用,运行其他对象的run方法。因此线程池中的线程并不会和具体的runnable绑定在一起,更像是container。

因为这个小程序是跑在window上的一个service,所以使用stopHander作为service停止的相应动作。各个子线程都应定时检查静态成员变量ifstop标志,发现后就应设法停止,从而令主线程pool.shutdown();     正常停止。

public static void stopHandler(String[] args) {
        ifStop = true;    
    }   
    public static boolean getIfStop(){
          return ifStop;
 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值