架构师课程1-多线程基础

原创
2017/07/07 13:49
阅读数 60

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 ConcurrentLinkedQueue<Task> workQueue = new ConcurrentLinkedQueue<>();
	private HashMap<String, Thread> workers = new HashMap<>();
	private ConcurrentHashMap<String, Object> result = new ConcurrentHashMap<>();

 

Message Queue : 本质就是有消息堆积能力的容器 RocketMQ.来缓解消费端压力。不能实现实时。如果要实时,建议使用TCP直连,例如mina 或者 netty.

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部