java多线程之并发编程

1.并发不必定比串行更快 由于并发有线程建立和上下文切换的开销
2.java的并发采用内存共享模型
3.单线程中重排序不会影响到结果 但多线程中重排序可能会影响到结果
4.votaile变量 当线程A修改votatile变量会更加主内存发送信息给B线程 修改的值刷新到主内存 被通知的线程将本地内存的votaile值设为无效 读取主内存更新的值 但只能保证其线程的可见性 不能保证原子性
5.votaile相比锁是轻量级的同步 简易性和可收缩性 不会形成线程阻塞 也就不会形成死锁问题 性能更高 votaile读操做和非votaile读操做性能同样 但写操做比非votaile写操做性能更低 若是线程变量读操做远多于写操做 voatile提升比锁提升更低的效率 适用 状态标记 boolean 一次性发布 在整个项目运行中不会存在这个变量的非原子性操做
6.CAS和votaile是ReentantLock和concurrent包的基石
7.乐观锁和悲观锁 独占锁就是悲观锁 sychronized就是独占锁 让须要锁的线程挂起等待持有锁线程的
释放乐观锁的实质是采用CAS 在不加锁 假设不冲突的状况下完成某项操做 若是冲突则重试直到成功 为止内部实现是经过java native 方法(JNI) CAS的缺陷 第一 ABA问题 当某个值为A 修改成B 但又改成 A 经过加版本的方式解决(时间戳)第二 循环时间长开销大 经过CPU暂停指令解决 第三只能对一个 共享变量进行原子性操做 能够采用多个变量合并的方式
8.JMM的核心是happens_before 对于锁若是只有单个线程访问则能够将锁消除 votaile变量若是只有单个线程访问则能够将votaile变量当成普通变量
9.越是追求性能的处理器 内存模型设计就越弱
10.守护线程不能经过finally中的输出语句来判断程序执行完毕和内存资源的释放 由于程序执行完毕也不必定会执行try finally中的语句
11.在开启线程使最好给线程取好线程名 以便可以快速查找问题所在
12.在获取同步状态时 同步器会维护一个同步队列 获取同步状态失败的线程被加入到同步队列中进行自旋 获取同步状态成功的线程也就是同步队列的头结点出队或者被中断就会被唤醒本身结点的后继结点获取到同步状态
13.synchronized能隐式的重入锁 lock方法则不能够但能够显式再调用lock方法获取锁
14.排他锁 非公平锁可能形成线程饥饿 但减小了线程的切换 保证了更大的吞吐量 效率更高
15.读写锁 写锁是可重进入的排他锁 读锁是可重进入的共享锁 一个int变量记录读写锁的状态 读锁占
高16位写锁占低16位(1<<16) 读写锁 锁降级是否必要 答案是必要的由于 虽然获取读锁 有写锁获取时 则会被进入等待状态 但写锁获取以前可能有读锁获取到读锁 因此须要锁降级再次获取读锁进行数据同步
16.LockSupport类主要是用来阻塞和唤醒队列 ReentantLock内部主要是经过votaile技术和CAS技术实现同步 内部有同步器对同步队列和等待队列的操做 获取同步状态时 同步器会将获取失败的线程放入同步队列中 当同步队列头结点即获取到同步状态的被中断或者是被移除同步队列 会唤醒后继结点获取同步状态 LockSupport能够将线程在等待队列和同步队列之间切换
17.ConcurrentHashMap内部是segment类和HashEntry数组 Segment继承了ReentantLock类实现同步操做 将map中的数据分为多段 每段的长度会不同 并加上锁 put方法是在segment上进行扩容加数据 采用的是哈希散列的方式再计算多段数据长度和时须要同步modCount方法判断容器是否有修改
18.ConcurrentLinkedQueue的入队方法永远返回的是true 不能经过入队方法判断是否入队成功
19.java是不能直接访问操做系统底层 只能经过本地方法访问 Unsafe是硬件级别的原子操做
第一 能够分配内存和释放内存 第二 阻塞和恢复线程(LockSupport) 第三CAS操做 第四 能够定位某对象的字段内存位置和修改对象字段值 即便是私有的
20.能够原子的更新引用类型 字段类 基本类型 数组 (AtomicReference)
21.CountDownLatch就是计数器当减到0时 await就不会阻塞当前线程了和CyclicBarrir的
22.Excharger类实现线程直接的交换数据
23.线程池的优势 第一 下降资源消耗 第二 缩短响应时间 第三提升对线程的管理性 线程的分配 调优 监控
24.线程池 当有个新任务进入线程池 没满则会建立新线程处理 若是线程池的基本数量的核心线程已经满了 会判断工做队列是否满了 没满则会放入阻塞队列中 若是满了 会让线程池建立新的线程处理这个任务 若是线程数量已经达到最大数量 则会执行饱和策略 默认是会报错 任务执行完了会去查看工做队列是否有任务若是有则会取出执行这个任务 若是工做队列空 而且当前线程池的线程数量大于基本数量则会被销毁 shutdown 和 shutdownNow方法 shutdownNow方法
25.建议使用有界的阻塞队列 须要有线程池的监控以方便知道线程各类状况 好比最大线程数
26.Excutors 方法fixThradPool CachedThreadPool是大小无界的线程池 适用于短时间异步执行的小程序 负载较轻的服务器
27.FutureTask未启动 时调用futureTask.cancel会致使任务不会被执行 FutureTask启动时 futureTask.cancel(true)会以中断的方式使任务 任务已经执行完 futureTask.cancel(*)会返回false
28.for(;;)好比while(1)好的缘由是指令少 不怎么占用寄存器 没有判断跳转
29.AQS实现的同步器于 ReentantLock ReentantReadWriteLock Semphore CountDownLatch FutureTask
30.多线程项目是比较难调试 因此须要打印好日志信息 以便及时查找问题所在 异常处理打印日志
和同步linux命令查看系统cup等相关的信息
31.ps -eLf}grep java -c 查看线程数是否增加
netstat -nat|grep 3306 -c 查看指定端口的数据库链接数
cat /proc/net/dev 查看网络流量
cat /proc/loadavg 查看系统平均负载
cat /proc/meminfo 查询系统内存使用状况
cat /proc/stat 查看CPU的利用率
32.根据任务类型或者任务的优先级进行不一样线程池的处理
相关文章
相关标签/搜索