使用Thread Pooling处理简短任务


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

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

J2SE5.0现在提供了全新的java.util.concurrent包,其中有几经构建好的线程池的框架。
例如:Executor接口提供了单独的一个办法execute来接收一个Runnable的实例对象:
public interface Executor {
public void execute(Runnable command);
}

所以我们可以创建一个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.
### 回答1: Adaptive pooling 是一种对图像进行重采样的方法,它可以根据输入图像的大小自适应地调整输出图像的大小。这种方法通常用于深度学习中,用来将不同大小的输入图像转换为统一的大小,以便进行处理。 ### 回答2: AdaptivePooling是一种比传统的OpenCV更为灵活的图像处理方法。传统的OpenCV是基于固定的算法和参数进行图像处理的,而AdaptivePooling则能够根据图像的特点和需要进行自适应地调整处理方法和参数。 AdaptivePooling的核心思想是根据图像的局部特点进行自适应地池化操作。传统的池化操作是将图像划分为固定的区域,然后对每个区域进行降采样操作。而AdaptivePooling则会根据图像的局部特点调整区域的大小,并根据不同区域内的特征进行不同的池化操作,以达到更好的图像处理效果。 与传统方法相比,AdaptivePooling具有以下几个优势。首先,它能够适应不同图像的尺寸和特点,无论是大图像还是小图像,都能够进行有效的处理。其次,它能够更好地保留图像的特征信息。传统的池化操作会导致信息的丢失,而AdaptivePooling则可以根据图像的特点灵活地进行池化操作,从而尽量保留图像的信息。最后,AdaptivePooling还可以用于解决一些特殊的图像处理问题,例如目标检测、边缘提取等。 总之,使用AdaptivePooling可以更加灵活地进行图像处理,不仅能够适应不同的图像尺寸和特点,还能够更好地保留图像的信息,解决特定的图像处理问题。相比之下,传统的OpenCV是基于固定算法和参数的,对于一些特殊的情况可能无法达到很好的处理效果。因此,AdaptivePooling是一种更为灵活和高效的图像处理方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值