Effective Java 第10章

第10章

第66条

1、Java中的原子操作:对于所有的变量(除long和double外)读和写操作都是原子的(互斥的)。(不会在写的中途被读取,成为一个奇怪的量,获取的值为写之前,或者是写之后的值)
2、虽然java中的变量是原子操作,但是必要时刻仍需要同步。
3、对于共享的数据,最好同步其动作。

第67条

CopyOnWriteArrayList:并发集合。写操作通过拷贝底层数组+锁实现,读操作不加锁。大量使用会影响使用。适用于读多写少。
缺点:会在某一时间存在一份拷贝,占用内存;只能保证最终一致性。

第68条

线程池:
Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;
ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;
抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;
然后ThreadPoolExecutor继承了类AbstractExecutorService。
Executors是一个工具类,通过简单工厂提供不同的线程池。

Executors提供四种线程池:
newCachedThreadPool :缓存线程池,如果线程池长度超过处理需要,可回收空闲线程,若无可回收,则新建线程。core=0,max=int_max。队列为SynchronousQueue,容量为0,容器相当于通道,本身不存储元素。
newFixedThreadPool : 定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。max=core,队列为LinkedBlockingQueue,容量为MAX_INTEGER。
newScheduledThreadPool : 计划线程池,支持定时及周期性任务执行。队列为LinkedBlockingQueue
newSingleThreadExecutor :单线程线程池,用唯一的线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。core=1,max=1,队列为DelayedWorkQueue

线程和任务:并不是每一个任务到了就会创建一个线程去执行。
当新提交一个任务时:
(1)如果poolSize<corePoolSize,新增加一个线程处理新的任务。
(2)如果poolSize=corePoolSize,新任务会被放入阻塞队列等待。
(3)如果阻塞队列的容量达到上限,且这时poolSize<maximumPoolSize,新增线程来处理任务。
(4)如果阻塞队列满了,且poolSize=maximumPoolSize,那么线程池已经达到极限,会根据饱和策略RejectedExecutionHandler拒绝新的任务。

  • corePoolSize :线程池的基本大小,即在没有任务需要执行的时候线程池的大小,并且只有在工作队列满了的情况下才会创建超出这个数量的线程。这里需要注意的是:在刚刚创建ThreadPoolExecutor的时候,线程并不会立即启动,而是要等到有任务提交时才会启动,除非调用了prestartCoreThread/prestartAllCoreThreads事先启动核心线程。再考虑到keepAliveTime和allowCoreThreadTimeOut超时参数的影响,所以没有任务需要执行的时候,线程池的大小不一定是corePoolSize。

  • maximumPoolSize:
    线程池中允许的最大线程数,线程池中的当前线程数目不会超过该值。如果队列中任务已满,并且当前线程个数小于maximumPoolSize,那么会创建新的线程来执行任务。

  • allowCoreThreadTimeOut:
    该属性用来控制是否允许核心线程超时退出。If false,core threads stay alive even when idle.If true, core threads use keepAliveTime to time out waiting for work。如果线程池的大小已经达到了corePoolSize,不管有没有任务需要执行,线程池都会保证这些核心线程处于存活状态。可以知道:该属性只是用来控制核心线程的。

keepAliveTime:
如果一个线程处在空闲状态的时间超过了该属性值,就会因为超时而退出。举个例子,如果线程池的核心大小corePoolSize=5,而当前大小poolSize =8,那么超出核心大小的线程,会按照keepAliveTime的值判断是否会超时退出。如果线程池的核心大小corePoolSize=5,而当前大小poolSize =5,那么线程池中所有线程都是核心线程,这个时候线程是否会退出,取决于allowCoreThreadTimeOut。

第69条

并发工具优先于wait和notify

  • Executor Framework 线程池
  • Concurrent Collection 并发集合
  • 同步器

并发集合:

  • ConcurrentHashMap
  • ConcurrentLinkedDeque
  • ConcurrentLinkedQueue

同步器:

  • CountDownLatch:一次性障碍,构造参数为int,表示在等待线程被处理之前得达到的数值。
  • Semaphore:信号量
  • CyclicBarrier:不常用
  • Exchanger:不常用

第71条

慎用延迟初始化
虽然降低了初始化的开销,但是却相应的增加了访问的开销。
实例域:采用双重检查模式
静态域:静态工厂构造,VM在构造静态类的时候实现了同步。

第72条

**不要依赖于线程调度器 **
yield:让出cpu时间给其它线程,有可能仍然自己获得cpu时间
不要通过yield以及线程优先级仅能作为应用级别的实现,而不能用其来解决程序中出现的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值