1. LockSupport比Object的wait/notify有两大优势:
①LockSupport不需要在同步代码块里 。所以线程间也不需要维护一个共享的同步对象了,实现了线程间的解耦。
②unpark函数可以先于park调用,所以不需要担心线程间的执行的先后顺序。
2. atomic基本原子类
compareAndSwapInt()通过原子的方式将期望值和内存中的值进行对比,如果两者相等,则执行更新操作。
staticFieldOffset()和objectFieldOffset()两方法分别提供两静态、非静态域的偏移量计算方法。
3. ReentrantLock和ReentrantReadWriteLock,在读和写都有的情况下选则可重入读写锁
4
. StampedLock是Java8引入的一种新的所机制,简单的理解,可以认为它是读写锁的一个改进版本,读写锁虽然分离了读和写的功能,使得读与读之间可以完全并发,但是读和写之间依然是冲突的,读锁会完全阻塞写锁,它使用的依然是悲观的锁策略.如果有大量的读线程,他也有可能引起写线程的饥饿
而StampedLock则提供了一种乐观的读策略,这种乐观策略的锁非常类似于无锁的操作,使得乐观锁完全不会阻塞写线程
5.乐观锁和悲观锁
即加锁是一种悲观策略,无锁是一种乐观策略,因为对于加锁的并发程序来说,它们总是认为每次访问共享资源时总会发生冲突,因此必须对每一次数据操作实施加锁策略。而无锁则总是假设对共享资源的访问没有冲突,线程可以不停执行,无需加锁,无需等待,一旦发现冲突,无锁策略则采用一种称为CAS的技术来保证线程执行的安全性
CAS在cpu的支持下是原子性操作
6. ArrayBlockingQueue是一个边界缓冲对流,底层是array,他是FIFO先进先出的。新插入的数据会被插入到队列的末尾,而且总是从队头取数据。
7. ConcurrentLinkedDeque有数目不详的元素列表,你可以添加、阅读、或删除任何位置的元素。
此外并发列表允许不同的线程列 表中添加或删除元素时不产生任何数据不一致, 非阻塞列表提供如下操作,
如果操作不能立即完成,列出抛出异常或者返回一个null值
8. CountDownLatch利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,
此时就可以利用CountDownLatch来实现这种功能了。
9. CyclicBarrier通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被
释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了
10 CountDownLatch和CyclicBarrier区别:
CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同:
CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;
CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;
另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。
11. Semaphore可以控同时访问的线程个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。
Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限。
==============================多线程==================================================
1.Executor 是所有和线程有关的接口;
2. countDownLatch: 来使用他做统计用,多个线程都执行完毕后,数据统一返回;
他相当于一个计数器功能, countdown方法是对count进行减一操作, 最后在await(); 方法;
检测count如果不为0,所有线程等待,未完成的线程返回结果; 最后统计返回个前端;
3. ThreadPoolExecutor实现了AbStractExectorServic,
他的构造方法参数有:
①.核心线程数,默认核心线程一直存活
② 线程池所容纳的最大线程数,超过这个数会被阻塞.在LinkedBlockingDeque时候才无效
③. keepAliveTime ,非核心线程闲置时间,超过这个时间会被回收
④. unit, 闲置单位
⑤. 线程池中任务队列;
synchronousQueue: 在核心线程用完了,就会在最大线程数情况下创建线程,超过后抛异常;
linkedBlockingDeque: 他就是超过核心线程数,就放在队列中排队;
ArrayBlockingQueue: 是一个阻塞式的队列,数组式的,性能不好,稳定;
⑥. threadFactory线程工厂可以对线程属性定制
⑦. RejectedEecutionHandler: 当添加新线程被拒绝的时候,会执行他的方法;
4.ExecutorService 是Executor的子接口 , 开启线程池的方法;
创建四种线程池:
①newFixedThreadPool 创建一个定长的线程,超出的线程会在队列中等待
②.newScheduledThredPool 创建一个定长的线程池,支持定时及周期性任务执行.
③.newCachedThreadPool 川建一个可缓存的线程池,如果线程池长度超过处理需要,可以灵活回收,若无可回收线程,则创建线程
④newSingleThreadExecutor 创建一个单线程化的线程池, 只会用唯一工作线程来执行任务,保证任务顺序执行优先级执行;
5. ThreadPoolTaskExecutor 异步方法;
①.无返回值的任务使用execute(Runnable)
②.有返回值使用submit(Runnable) , 使用Future对象封装返回值.
shutdown则只是将线程池的状态设置为shutdown,然后中断所有没有执行任务的线程,并将剩余的任务执行完。
通过继承线程池,重写beforeExecute,afterExecute和terminated方法来在线程执行任务前,
线程执行任务结束,和线程终结前获取线程的运行情况,根据具体情况调整线程池的线程数量。
TaskExecutor.execute(new OverDueTask(orderInfoRedis, now)) 异步方法;
比如 渠道统计:
一张渠道表: 设及到子父级渠道;
一张用户注册表: 用户注册时,统计的百分比,
一张用户详细信表: 还有用户详细表中用户渠道首次借款超过10天统计状态 到底统不统计
一张订单表: 用户首次借款额度;借款成功次数,
筛选条件为用户注册时间 开始日期到结束日期;
首先就是判断用户选择日期间隔,是否大于10天
大于10天: 两天一个线程
小于10天: 一天一个线程