一点点core java的笔记-并发
并发
Runnable 函数式接口(只有一个函数 run),可用 lamba建立实例
Thread t = new Thread (()→{... }), t.start ()
获取当前线程:Thread. current Thread ()
中断线程: 调用 interrupt方法,将线程中断状态改为true。当线程在 sleep or wait状态时,调用interrupt会被interrupt Exception 中断, 要记得在sleep 后 调用thread. interrupt 设中断或直接在方法中抛出异常(更好)。
线程状态
New 状态:
Runnable 状态:调用 start,可能在运行也可能没有, (抢占调度等)
Blocked/Waiting:
- 当线程获取内部对象锁时(145.3,145.5)
- 当代程等另一个线程的条件时 (14.5.4)
- 超时参数, Thread. sleep (20)
Terminated: run 方法或未捕获异常
线程属性:
- 线程优先级在 Thread中 1~10。用 setPriority 改,但依轻于系统可能无效。
- 用 thread. Set Daemon (true) 把线程认为是守护线程,为其它线程服务
- 非受查异常使线程死亡前,异常被传至一个处理器。可用thread. set Uncaught Exception Handler为线程设或Thread. set Default...为所有设。传入实现Thread. Uncaught Exception. Handler接口(函数式接口)
- 线程组略
同步
竞争条件举例:多个线程同时进行账户存取,银行总余额改变。
原因:线程1将数据加入寄存器并修改,此时线程2若完成修改,线程1将数据,写回会覆盖线程2。
方案:
Reentrant Lock 每个对象都有自己的 Reentrant Lock对象。(可重入锁)
可重入:例如在一个被锁保护的代码中用了使用同个锁的方法,锁对象的持有计数就为2(被lock 了2次)
条件对象
await:若当前线程被阻塞了且放弃了锁,调用该锁对象new Condition 的 await (当转出钱大于余额时)。
当其它线程在完成进账后调用同条件的 condition. signal All 方法时解除这些阻塞。
通常用 while (无法继续){ condition. await;}
解决死锁: 当有利于等待进程改变方向时就使用signalAll。也可用 signal,随机解除一个阻塞进程,但有风险。
synchronized (同步):
方法若用 synchronized声明,对象锁会保护方法。且在其中调用wait/notifyAll / notify = await/sinalAll/signal。静态类也可使用
监视器:
volatile 修饰变量,不会引响线程的同步更新与获取(原子性)
声明域为 final,可保证其它线程看到的都是初始化的值
死锁:条件判定做好
ThreadLocal <T> 为每个线程提供自己的实例。
在某一线程首次 get 时,会初始化值。
tryLock P 665
读写锁:多读少改时
弃用 stop: stop 方法会终止所有未结束方法。难以确定何时安全。
阻塞队列:生产者插入元素,消费者拿出,队满或队空(无法继续)时自动阻塞。
映射的更新: ConcurrentHashMap
replace (key, oldV, newV)以原子方式改值,当之前没有原值的修改时反回 true。
compute (key,函数)例
批操作: P678
并发集视图:
Copy On Write Array List, 是对低层数组的引用, 仿问迭代器无须同步开销。
执行器(Executor)
线程池: 大量短生命期线程, run 方法退出时线程不死亡,、准,备为下个线程服务。可限制并发线程数。
newCachedThreadPool: 有空线程时执行任务,无 时新建空闲线程。
newFixedThreadPool:固定大小,多余任务放入队列。
newSingleThreadExecutor:大小为1
反回实现了 Executor Service接口的 Tread Pool Executor对象。