Java并发编程实现—Concurrent—之简介概要篇

来源:互联网 发布:淘宝网积分怎么兑换 编辑:程序博客网 时间:2024/05/29 11:11

在并发编程中实用工具类

 


第一章 关键接口

 

1.BlockingQueue<E>

支持两个附加操作的 Queue,这两个操作是:检索元素时等待队列变为非空,以及存储元素时等待空间变得可用。 

 

2.Callable<V>

返回结果并且可能抛出异常的任务。 

 

3.CompletionService<V>

将生产新的异步任务与使用已完成任务的结果分离开来的服务。 

 

4.ConcurrentMap<K,V>

提供其他原子 putIfAbsent、remove、replace 方法的 Map。 

 

5.Delayed 

一种混合风格的接口,用来标记那些应该在给定延迟时间之后执行的对象。 

 

6.Executor 

执行已提交的 Runnable 任务的对象。 

 

7.ExecutorService Executor

提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 

 

8.Future<V> Future 

表示异步计算的结果。 

 

9.RejectedExecutionHandler 

无法由 ThreadPoolExecutor 执行的任务的处理程序。 

 

10.ScheduledExecutorService 

一个 ExecutorService,可安排在给定的延迟后运行或定期执行的命令。 

 

11.ScheduledFuture<V> 

一个延迟的、结果可接受的操作,可将其取消。 

 

12.ThreadFactory

 根据需要创建新线程的对象。 

 


 

 第二章 关键类


1.AbstractExecutorService 

提供 ExecutorService 执行方法的默认实现。 

 

2.ArrayBlockingQueue<E> 

一个由数组支持的有界阻塞队列。 

 

3.ConcurrentHashMap<K,V> 

支持检索的完全并发和更新的所期望可调整并发的哈希表。 

 

4.ConcurrentLinkedQueue<E> 

一个基于链接节点的、无界的、线程安全的队列。 

 

5.CopyOnWriteArrayList<E> 

ArrayList 的一个线程安全的变体,其中所有可变操作(添加、设置,等等)都是通过对基础数组进行一次新的复制来实现的。 

 

6.CopyOnWriteArraySet<E> 

对其所有操作使用 CopyOnWriteArrayList 的 Set。 

 

7.CountDownLatch 

一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 

 

8.CyclicBarrier

 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。 

 

9.DelayQueue<E extends Delayed>

Delayed 元素的一个无界阻塞队列,只有在延迟期满时才能从中提取元素。 

 

10.Exchanger<V> 

两个线程可以交换对象的同步点。 

 

11.ExecutorCompletionService<V> 

使用提供的 Executor 来执行任务的 CompletionService。 

 

12.Executors 

此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、13.ThreadFactory 和 Callable 类的工厂和实用方法。 

 

14.FutureTask<V> 

可取消的异步计算。 

 

15.LinkedBlockingQueue<E> 

一个基于已链接节点的、范围任意的 blocking queue。 

 

16.PriorityBlockingQueue<E> 

一个无界的阻塞队列,它使用与类 PriorityQueue 相同的顺序规则,并且提供了阻塞检索的操作。 

 

17.ScheduledThreadPoolExecutor 

ThreadPoolExecutor,它可另行安排在给定的延迟后运行命令,或者定期执行命令。 

 

18.Semaphore 

一个计数信号量。 

 

19.SynchronousQueue<E> 

一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。 

 

20.ThreadPoolExecutor 

一个 ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用 Executors 工厂方法配置。 

 

21.ThreadPoolExecutor.AbortPolicy

 用于被拒绝任务的处理程序,它将抛出 RejectedExecutionException. 

 

22.ThreadPoolExecutor.CallerRunsPolicy 

用于被拒绝任务的处理程序,它直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务。 

 

23.ThreadPoolExecutor.DiscardOldestPolicy 

用于被拒绝任务的处理程序,它放弃最旧的未处理请求,然后重试 execute;如果执行程序已关闭,则会丢弃该任务。 

 

24.ThreadPoolExecutor.DiscardPolicy

 用于被拒绝任务的处理程序,默认情况下它将放弃被拒绝的任务。 

 



第三章 概要说明

执行程序

接口。Executor 是一个简单的标准化接口,用于定义类似于线程的自定义子系统,包括线程池、异步 IO 和轻量级任务框架。根据所使用的具体 Executor 类的不同,可能在新创建的线程中,现有的任务执行线程中,或者调用execute() 的线程中执行任务,并且可能顺序或并发执行。ExecutorService 提供了多个完整的异步任务执行框架。ExecutorService 管理任务的排队和安排,并允许受控制的关闭。ScheduledExecutorService 子接口添加了对延迟的和定期任务执行的支持。ExecutorService 提供了安排异步执行的方法,可执行由Callable 表示的任何函数,结果类似于 RunnableFuture 返回函数的结果,允许确定执行是否完成,并提供取消执行的方法。

实现。ThreadPoolExecutorScheduledThreadPoolExecutor 提供可调的、灵活的线程池。Executors 类提供大多数 Executor 的常见类型和配置的工厂方法,以及使用它们的几种实用工具方法。其他基于 Executor 的实用工具包括具体类FutureTask,它提供 Future 的常见可扩展实现,以及 ExecutorCompletionService,它有助于协调对异步任务组的处理。

队列

java.util.concurrent ConcurrentLinkedQueue 类提供了高效的、可伸缩的、线程安全的非阻塞 FIFO 队列。java.util.concurrent 中的五个实现都支持扩展的BlockingQueue 接口,该接口定义了 put 和 take 的阻塞版本:LinkedBlockingQueueArrayBlockingQueueSynchronousQueuePriorityBlockingQueueDelayQueue。这些不同的类覆盖了生产者-使用者、消息传递、并行任务执行和相关并发设计的大多数常见使用的上下文。

计时

TimeUnit 类为指定和控制基于超时的操作提供了多重粒度(包括纳秒级)。该包中的大多数类除了包含不确定的等待之外,还包含基于超时的操作。在使用超时的所有情况中,超时指定了在表明已超时前该方法应该等待的最少时间。在超时发生后,实现会“尽力”检测超时。但是,在检测超时与超时之后再次实际执行线程之间可能要经过不确定的时间。

同步器

四个类可协助实现常见的专用同步语句。Semaphore 是一个经典的并发工具。CountDownLatch 是一个极其简单但又极其常用的实用工具,用于在保持给定数目的信号、事件或条件前阻塞执行。CyclicBarrier 是一个可重置的多路同步点,在某些并行编程风格中很有用。Exchanger 允许两个线程在集合点交换对象,它在多流水线设计中是有用的。

并发 Collection

除队列外,此包还提供了几个设计用于多线程上下文中的 Collection 实现:ConcurrentHashMapCopyOnWriteArrayListCopyOnWriteArraySet

此包中与某些类一起使用的“Concurrent&rdquo前缀;是一种简写,表明与类似的“同步”类有所不同。例如,java.util.HashtableCollections.synchronizedMap(new HashMap()) 是同步的,但ConcurrentHashMap 则是“并发的”。并发集合是线程安全的,但是不受单个排他锁定的管理。在 ConcurrentHashMap 这一特定情况下,它可以安全地允许进行任意数目的并发读取,以及数目可调的并发写入。需要通过单个锁定阻止对集合的所有访问时,“同步”类是很有用的,其代价是较差的可伸缩性。在期望多个线程访问公共集合的其他情况中,通常“并发”版本要更好一些。当集合是未共享的,或者仅保持其他锁定时集合是可访问的情况下,非同步集合则要更好一些。

大多数并发 Collection 实现(包括大多数 Queue)与常规的 java.util 约定也不同,因为它们的迭代器提供了弱一致的,而不是快速失败的遍历。弱一致的迭代器是线程安全的,但是在迭代时没有必要冻结集合,所以它不一定反映自迭代器创建以来的所有更新。




第四章 案例

一个简单的例子:

 

class TaskWithResult implements Callable<String>

{

    private int id;

 

    public TaskWithResult(int id)

    {

        this.id = id;

    }

 

    @Override

    public String call() throws Exception

    {

        return "result of TaskWithResult " + id;

    }

}

public class CallableTest

{

    private static int i=1;

 

public static void main(String[] args) throws InterruptedException,ExecutionException

      {

        ExecutorService exec = Executors.newCachedThreadPool();

        Future<String>results;

        results=exec.submit(new TaskWithResult(i));

        results.isDone();

        System.out.println(results.get());

        exec.shutdown();

       }

 

}

 


 

 

第五章 关键类的分析说明





接口 Executor

 

 

    执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。通常使用 Executor 而不是显式地创建线程。例如,可能会使用以下方法,而不是为一组任务中的每个任务调用 new Thread(new(RunnableTask())).start(): 

    

         Executor executor = anExecutor;

         executor.execute(new RunnableTask1());

         executor.execute(new RunnableTask2());

 

 

 class SerialExecutor implements Executor

{

     final Queue<Runnable> tasks = new ArrayDeque<Runnable>();

     final Executor executor;

     Runnable active;

 

     SerialExecutor(Executor executor)     

     {

         this.executor = executor;

     }

 

     public synchronized void execute(final Runnable r)      

    {

         tasks.offer(new Runnable()       

         {

             public void run()             

             {

                 try                 

                 {

                     r.run();

                 }                  

                  finally                  

                 {

                     scheduleNext();

                 }

             }

         });

         if (active == null)         

        {

             scheduleNext();

         }

     }

 

     protected synchronized void scheduleNext()    

     {

         if ((active = tasks.poll()) != null)         

        {

             executor.execute(active);

         }

     }

 }

 

ExecutorService

    提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成Future 的方法。可以关闭ExecutorService,这将导致其拒绝新任务。提供两个方法来关闭 ExecutorServiceshutdown() 方法在终止前允许执行以前提交的任务,而shutdownNow() 方法阻止等待任务启动并试图停止当前正在执行的任务。在终止时,执行程序没有任务在执行,也没有任务在等待执行,并且无法提交新任务。应该关闭未使用的ExecutorService 以允许回收其资源。通过创建并返回一个可用于取消执行和/或等待完成的Future,方法 submit 扩展了基本方法Executor.execute(java.lang.Runnable)。方法invokeAnyinvokeAll 是批量执行的最常用形式,它们执行任务 collection,然后等待至少一个,或全部任务完成(可使用ExecutorCompletionService 类来编写这些方法的自定义变体)。Executors 类提供了用于此包中所提供的执行程序服务的工厂方法。

 

  class NetworkService implements Runnable

 {

    private final ServerSocket serverSocket;

    private final ExecutorService pool;

 

    public NetworkService(int port, int poolSize)throws IOException 

    {

        serverSocket = new ServerSocket(port);

        pool = Executors.newFixedThreadPool(poolSize);

    }

 

    public void run() 

    { 

      try 

      {

        for (;;) 

        {

              pool.execute(new Handler(serverSocket.accept()));

        }

      } 

    catch (IOException ex) 

    {

        pool.shutdown();

    }

    }

  }

 

  class Handler implements Runnable 

{

    private final Socket socket;

    Handler(Socket socket) { this.socket = socket; }

    public void run() 

    {

    }

 }

 

 下列方法分两个阶段关闭 ExecutorService。第一阶段调用 shutdown 拒绝传入任务,然后调用 shutdownNow(如有必要)取消所有遗留的任务: 

 void shutdownAndAwaitTermination(ExecutorService pool) 

{

   pool.shutdown(); 

   try 

   {

          if (!pool.awaitTermination(60, TimeUnit.SECONDS)) 

        {

               pool.shutdownNow(); 

               if (!pool.awaitTermination(60, TimeUnit.SECONDS))

               System.err.println("Pool did not terminate");

        }

   } 

    catch (InterruptedException ie)

     {

         pool.shutdownNow();

         Thread.currentThread().interrupt();

     }

 }

 

Future

Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。计算完成后只能使用 get 方法来检索结果,如有必要,计算完成前可以阻塞此方法。取消则由cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用Future但又不提供可用的结果,则可以声明Future<?> 形式类型、并返回 null 作为基础任务的结果。

 

 interface ArchiveSearcher { String search(String target); }

 

 class App 

{

   ExecutorService executor = ...

   ArchiveSearcher searcher = ...

   void showSearch(final String target) throws InterruptedException

{

     Future<String> future = executor.submit(new Callable<String>() 

    {

         public String call() 

        { 

              return searcher.search(target); 

        }

     });

     displayOtherThings(); 

     try 

    {

       displayText(future.get()); 

     } 

    catch (ExecutionException ex) 

    { 

        cleanup(); 

        return; 

    }

   }

 }

ConcurrentLinkedQueue

 

    一个基于链接节点的、无界的、线程安全的队列。此队列按照 FIFO(先进先出)原则对元素进行排序。队列的头部 是队列中时间最长的元素。队列的尾部 是队列中时间最短的元素。新的元素插入到队列的尾部,队列检索操作从队列头部获得元素。当许多线程共享访问一个公共 collection 时,ConcurrentLinkedQueue 是一个恰当的选择。此队列不允许 null 元素。

 





主要参考: Java JDK 说明文档