并发总结

该文档从三个方面来总结并发:

一,线程安全

什么是线程安全?

同一段代码多线程运行与单线程运行,每次结果都一样并且结果与预期一致,就是线程安全。换言之多线程并没有导致数据与预期不一致。

简单例子:

不安全的ArrayList添加元素。如果单线程添加元素,没有问题。如果有两个线程添加元素,A线程欲在position=0位置添加数字10,在还没有添加进去时,此时B线程也在添加数据,结果B把position=0位置数据添加为20,此时A线程工作position=0位置数据改为10。与预期不一致,预期ArrayList中有两个数据10,20.现在只有一个数据10。

如何做到线程安全?

synchronized关键字方案:

通过将多线程共享的资源添加一把锁,这样每个线程访问共享资源就都是串行访问,不会出现线程不安全的问题。

synchronized(lock){
      doSomething(resource)      
}
sychronized 示例

synchronized底层如何实现?

synchronized关键字在字节码层面上将其monitorenter,monitorexit两个成对原语。 

二,线程可见性

因为一个系统可能有多颗CPU,为了保证一个线程中对一个变量的修改,在另外一个线程中被看见,所以有了线程可见性的问题。一般采用volatile关键字实现。

三,线程池

Java基础中熟悉一种线程池框架就可以应对工作中90%的场景:Executor框架

/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default thread factory and rejected execution handler.
     * It may be more convenient to use one of the {@link Executors} factory
     * methods instead of this general purpose constructor.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

搞懂Executor只需要搞明白上面这个构造函数就可以。

  1. taskCount<=corePoolSize:用该线程池中缓存的线程去执行task
  2. taskCount>corePollSize && taskCount<maxPoolSize:新建线程(maxPoolSize-corePoolSize)来应对多余的task
  3. taskCount>maxPoolSize:多余的task的放到queue中等待,等待时间为keepAliveTime,如果超时采用RejectedExecutionHandler来处理
    • AbortPolicy
    • CallerRunsPolicy
    • DiscardOldestPolicy
    • DiscardPolicy

 该线程池还是非常清晰明白了。

 

四,concurrent包内容

该包下都是并发的好东西,拣上面比较重要的总结下

Atomic

满足原子的对各种数据类型的对象进行操作 

locks

 

 

queue

 

 

并发组件

posted @ 2015-10-21 13:36  欣欣王  阅读(374)  评论(0编辑  收藏  举报