Static Synchronised 是类级别的锁,独占的 绝对同步, 可以跨多对象同步。
Synchronised 是对象锁,对每一个对象加锁 。
Synchronised 的方法或快是相对安全 一般用于set value时用,而不是get value
Oracle: undo 作用是当客户端DML操作时,oracle 是把旧值放入undo表空间,如果操作中途失败,去undo 找出来 回滚回去用的。因此 oracle 是consistent read 的,客户端9点找数据,就查9点时候的数据。如果中途有人DML操作,则一致性读特性就提示用户数据变了 报一个错 snapshot too old exception;
Synchronised 方法可以循环嵌套
Synchronised 内部有异常的话 锁自动释放
Synchronised 块 可以锁 类 和 变量 ,synchronised (this) or synchronised (new Object (“”))
Volatile :变量在各个线程中可见,每个线程都可以修改volatile 变量,但不具备原子性
AtomicInteger:支持多线程可见并发的原子操作,集成了volatile 适合多线程+ - 步长
Wait/notify: 线程之间的通信,必须配合synchronised 使用,wait 释放锁 notify 不释放锁。
两个线程互相通信可以写成死循环的形式互相监控 但是这样实现很不好,改进:
Final Object lock = new Object();Thread t1 = new Thread(new Runnable(){ syncronised(lock) { if (list.size() == 5) { // 发出通知 唤醒另外一边的线程 ,另一边一定是在wait,并没有释放lock锁,所以不会立刻通知,运行完才释放 lock.notify(); } }},"t1");Thread t2 = new Thread(new Runnable(){ syncronised(lock) { if (list.size() != 5) { lock.wait(); // 等待被唤醒 } logger.debug("还没有被唤醒"); }},"t2");// 注:t2必须先执行,先开始等待 再t1进行通知才可以!
实现实时的通知唤醒效果:
Final CountDownLatch countDownLatch = new CountDownLatch (1);Thread t1 = new Thread(new Runnable(){ if (list.size() == 5) { countDownLatch.countDown(); //发通知 }},"t1");Thread t2 = new Thread(new Runnable(){ if (list.size() != 5) { countDownLatch.await(); // 等待被唤醒 } logger.debug("还没有被唤醒");},"t2");
LinkedBlockingQueue : 就是用wait 和 notify + linkedlist 制作的
单利模式支持多线程:static inner class模式 + holder 模式, 如果是单利,hashcode()一定一样
public class Sing { private static class InnerSign { private static InnerSign holder = new InnerSing(); } public static Sing getInstance() { return InnerSign.holder; // lazy loading }}
让集合线程安全: Collections.syncronisedMap(new HashMap<String,String>())
并发类容器:
-ConcurrentMap容器实现是用减少锁力度的方法,分成多个小的hashtable()叫做segment然后对每一个segment加锁。
ConcurrentHashMap() // 无序的 ConcurrentSkipListMap() //有序的
-CopyOnWrite容器,当对一个元素执行写操作时,不对当前容器操作,先copy一个副本,对新的操作,然后指引用到旧的容器,这样就可以并发读操作,实现了读写分离 读多写少下使用多。
CopyOnWriteArrayList() CopyOnWriteArraySet()
ConcurrentLinkedQueue() //先进先出,非阻塞,不可以为null
ArrayBlockingQueue // 有界的,一般并发访问很大的时候用 对超过界限时候做一个处理策略
LinkedBlockingQueue // 无界的,性能比较好,在数据来的不大时候可以选用
SynchronousQueue(); // 没有缓冲队列 生产了会直接被消费,不直接add元素,必须先take才能add
PriorityBlockingQueue() // 里面元素<Item>必须实现Comparable接口 ,一个有优先级的队列
DelayQueue() // 带有延迟时间的队列,设一个延迟时间 当时间到了元素自动出来,多用于任务超时处理,里面东东必须实现Delayed借口。
-----------------------------------------------------------------------------------------------------
Future模式:请求后直接返回一个假对象,后台慢慢加载真实数据,加载完了再返回。异步加载
Master-worker 模式:Master主要负责接收和分配任务 Worker负责处理任务,好处是讲大任务分解成小任务,并行计算。手写strorm。
实现代码可以参考:
private ConcurrentLinkedQueueworkQueue = new ConcurrentLinkedQueue<>(); private HashMap workers = new HashMap<>(); private ConcurrentHashMap result = new ConcurrentHashMap<>();
Message Queue : 本质就是有消息堆积能力的容器 RocketMQ.来缓解消费端压力。不能实现实时。如果要实时,建议使用TCP直连,例如mina 或者 netty.