Java并发工具包之印象篇三

转摘于http://www.importnew.com/26461.html

 

1、执行器服务ExecutorService

该接口表示一个异步执行机制,使我们能够在后台执行任务。因此一个ExecutorService类似一个线程池。实际上,存在于java.util.concurrent包里的ExecutorService实现就是一个线程池实现

简单的ExcutorService例子

ExecutorService executorService = Executors.newFixedThreadPool(10);  
 
executorService.execute(new Runnable() {  
    public void run() {  
        System.out.println("Asynchronous task");  
    }  
});  
 
executorService.shutdown();

首先使用newFixedThreadPool工厂方法创建一个ExecutorService。上面创建了是个十个线程执行任务的线程池。然后,将一个Runnable接口的匿名实现类传递给execute方法。这将导致ExecuteorService中的某个线程执行该Runnable。

 

一个线程将一个任务委派给一个ExecutorService去异步执行。 一旦该线程将任务委派给ExecutorService,该线程将继续它自己的执行,独立于该任务的执行。

 

ExecutorService接口的实现类: ThreadPoolExecutor    ScheduledThreadPoolExecutor

可以使用Executors工厂类来创建ExecutorService

ExecutorService exe_1 = Executors.newSigleThreadExecutor();

ExecutorService exe_2 = Executors.newFixedThreadPool(10);

ExecutorService exe_3 = Executors.newScheduledThreadPool(10);

 

有几种不同的方式将任务委托给ExecutorService去执行

1、execute(Runnable)

ExecutorService exe = Executors.newSingleThreadExecutor();

exe.execute(new Runnable() {

    public void run() {

          System.out.println("asynchronous task");

    }

});

exe.shutdown();

无法得知被执行的Runnable结果。如果有需要可使用Callable

 

2、submit(Runnable)

返回一个Future对象,这个Future对象用来检查Runnable是否已经执行完毕

Future future = executorService.submit(new Runnable() {

     public void run() {

           System.out.println("task");

     }

});

future.get(); 如果task执行完返回null

 

3、submit(Callable)

该方法类似于submit(Runnable)方法。 Callable实例除了它的call方法能够返回一个结果之外和一个Runnable和像。Runnable.run不能返回一个结果。  Callable的结果可以通过submit(Callable)方法返回的Future对象进行获取

Future future = executorService.submit(new Callable() {
      public Object call() throws Exception {
             return "callable result";   
      }
});
future.get();  //result
 
4、invokeAny方法要求一系列的Callable或者其子接口的实例对象。调用这个方法并不会返回一个Future,但它返回一个Callable对象的结果。无法保证返回的是哪个Callable的结果--只能表明其中一个已执行结束
如果其中一个任务执行结束或者抛出一个异常,其他Callable将被取消
 
ExecutorService executorService = Executors.newSingleThreadExecutor(); 
 
Set<Callable<String>> callables = new HashSet<Callable<String>>(); 
 
callables.add(new Callable<String>() { 
    public String call() throws Exception { 
        return "Task 1"
    
}); 
callables.add(new Callable<String>() { 
    public String call() throws Exception { 
        return "Task 2"
    
}); 
callables.add(new Callable<String>() { 
    public String call() throws Exception { 
        return "Task 3"
    
}); 
 
String result = executorService.invokeAny(callables); 
 
System.out.println("result = " + result); 
 
executorService.shutdown();
 

5、invokeAll

该方法将调用你在集合传给ExecutorService的所有Callable对象。该方法返回一系列的Future对象,通过它们可以获取每个Callable的执行结果。 记住,一个任务可能会由于一个异常而结束,因此它可能没有成功。 无法通过一个Future对象来告知我们是两种结束中的哪一种。

ExecutorService executorService = Executors.newSingleThreadExecutor(); 
 
Set<Callable<String>> callables = new HashSet<Callable<String>>(); 
 
callables.add(new Callable<String>() { 
    public String call() throws Exception { 
        return "Task 1"
    
}); 
callables.add(new Callable<String>() { 
    public String call() throws Exception { 
        return "Task 2"
    
}); 
callables.add(new Callable<String>() { 
    public String call() throws Exception { 
        return "Task 3"
    
}); 
 
List<Future<String>> futures = executorService.invokeAll(callables); 
 
for(Future<String> future : futures){ 
    System.out.println("future.get = " + future.get()); 
 
executorService.shutdown();
 
要终止ExecutorService里的线程需要调用shutdown方法,ExecutorService并不会理解关闭,但它将不再接受新的任务,而且一旦所有线程都完成了当前任务的时候,ExecutorService将会关闭。在shutdown被调用之前所有提交给ExecutorService的任务都被执行。如果想要立即关闭ExecutorService,可以调用shutdownNow方法。这样会立即尝试停止所有执行中的任务,兵忽略哪些已提交但尚未开始处理的任务。无法担保执行任务的正取执行。可能它们被停止了,也可能已经执行结束。
 
####################################################
 
2、线程池执行者ThreadPoolExecutor
 
其使用内部池中的线程执行给定任务(Callable或者Runnable)。 ThreadPoolExecutor包含的线程池能够包含不同数量的线程。池中线程的数量由以下变量决定:
 
* corePoolSize
* maximumPoolSize
 
当一个任务委托给线程池时,如果池中线程数量低于corePoolSize,一个新的线程将被创建,即使池中可能尚有空闲线程。如果内部任务队列已满,而且有至少corePoolSize正在运行,但是运行线程的数量低于maximumPoolSize,一个新的线程将被创建去执行该任务。
 
int  corePoolSize  =    5
int  maxPoolSize   =   10
long keepAliveTime = 5000
 
ExecutorService threadPoolExecutor = 
        new ThreadPoolExecutor( 
                corePoolSize, 
                maxPoolSize, 
                keepAliveTime, 
                TimeUnit.MILLISECONDS, 
                new LinkedBlockingQueue<Runnable>() 
                );

################################################

3、定时执行者服务ScheduledExecutorService

它能够将任务延后执行,或者间隔固定时间多次执行。任务由一个工作者线程异步执行,而不是由提交任务给ScheduledExecutorService的那个线程执行

 

简单示例

ScheduledExecutorService scheduledExecutorService =  
        Executors.newScheduledThreadPool(5);  
 
ScheduledFuture scheduledFuture =  
    scheduledExecutorService.schedule(new Callable() {  
        public Object call() throws Exception {  
            System.out.println("Executed!");  
            return "Called!";  
        }  
    }, 5, TimeUnit.SECONDS);

一个内置五个线程的ScheduledExecutorService被创建。之后一个Callable接口的匿名类示例被创建然后传递给schedule方法。 后边的两参数定义了Callable将在5秒钟之后执行。

 

ScheduledExecutorService 实现ScheduledThreadPoolExecutor

 

ScheduledExecutorService 使用

1、schedule (Callable task, long delay, TimeUnit timeunit)

该方法计划指定的Callable在给定的延迟之后执行。这个方法返回一个ScheduledFuture,通过它可以在它被执行之前对它进行取消,或者在它执行之后获取结果。

ScheduledExecutorService scheduledExecutorService =  
        Executors.newScheduledThreadPool(5);  
 
ScheduledFuture scheduledFuture =  
    scheduledExecutorService.schedule(new Callable() {  
        public Object call() throws Exception {  
            System.out.println("Executed!");  
            return "Called!";  
        }  
    },  
    5,  
    TimeUnit.SECONDS);  
 
System.out.println("result = " + scheduledFuture.get());  
 
scheduledExecutorService.shutdown();

 

2、schedule (Runnable task, long delay, TimeUnit timeunit)

除了 Runnable 无法返回一个结果之外,这一方法工作起来就像以一个 Callable 作为一个参数的那个版本的方法一样,因此 ScheduledFuture.get() 在任务执行结束之后返回 null。

 

3、scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)

该方法规划一个任务将被定期执行。该任务将会在首个initialDelay之后得到执行,然后每个period时间之后重复执行。如果给定任务的执行抛出了异常,该任务将不再执行。如果没有任何异常的话,这个任务将会持续循环执行到ScheduledExecutorService被关闭。如果一个任务占用了比计划的时间间隔更长的时候,下一次执行将在当前执行结束执行菜开始。 计划任务在同一时间不会有多个线程同时执行。
 
4、scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)
除了 period 有不同的解释之外这个方法和 scheduleAtFixedRate() 非常像。  scheduleAtFixedRate 方法中,period被解释为前一个执行的开始和下一个执行的开始之间的间隔时间。而在本方法中,period则被解释为前一个执行的结束和下一个执行的结束之间的间隔。 因此这个延迟是执行结束之间的间隔,而不是执行开始之间的间隔。
posted @ 2018-05-15 16:36  秋水秋色  阅读(111)  评论(0编辑  收藏  举报