一  线程基础
1、synchronized取得的锁都是对象锁,哪个线程执行synchronized修饰的方法,哪个线程就获得这个方法所属对象的锁。不同对象不同锁,互不影响。
另一种情况是static静态方法加synchronized表示类级别的锁,锁定.class类。如:
public static synchronized void printNum(String tag)
2、脏读
ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的数据库,必需要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。
Oracle中undo:相当于日志,数据库在执行DML操作时会把旧值放到undo里,这样可以实现回滚。
3、synchronized细节
  3.1 synchronized锁重入:当一个线程得到一个对象的锁后,再次请求此对象时可以再次得到该对象的锁。若出现异常,锁自动释放。此时要及时处理!
  3.2 涉及父子继承,synchronized修饰父的方法和子的方法实现加锁,也没问题。
  3.3 synchronized代码块可以对任意的Object加锁(不要对字符串常量加锁,会出现死循环,可以new一个String对象)。
       当对象本身发生了改变,这个锁就变了。如:String loc = “a”; loc = “b”; //这就变了
       但如果对象本身不变,对象的属性值改变,那锁还是不变。如:
      Final Student s = new Student(); s的名字年龄值改变,但还是多个Thread中同一个s调用方法,那还是同步。
4、Volatile
  Volatile关键字只能让成员变量在多个线程之间可见。但它不能保证变量的原子性,要实现原子性建议使用atomic类的系列对象(注意atomic类只保证本身方法原子性,不保证多次操作的原子性):
  private static AtomicInteger count = new AtomicInteger(0);
  count.incrementAndGet(); // 相当于++。
  volatile算轻量级synchronized,性能强于synchronized,不会造成阻塞。
5、wait、notify
  使用wait、notify实现线程间通信。这两个方法都是Object类的方法,也就是说java为所有的对象都提供了这两个方法。
  它俩必须配合synchronized使用。
  wait方法释放锁,notify方法不释放锁。
6、ThreadLocal
  线程局部变量。它完全不提供锁,而使用以空间换时间的方式,为每个线程提供变量的独立副本,以保障线程安全。高并发时可以用它。
7、多线程的单例模式
  需要用dubble check Instance或static inner class。
8、同步类容器:线程安全的,如Vector、HashTable;
    经典错误ConcurrentModificationException:比如当容器迭代过程中,被并发的修改了内容。
9、并发类容器:jdk5以后出现,如ConcurrentHashMap代替HashTable,CopyOnWriterArryList代替Vector等等,详见
10、并发Queue
  Jdk提供两套并发队列实现,这两套都继承Queue:
  10.1 以ConcurrentLinkedQueue为代表:高性能队列,适用于高并发场景下的队列,无锁。
  10.2 以BlockingQueue为代表:阻塞队列
      a. ArrayBlockingQueue有界队列
      b. LinkedBlockingQueue无界队列
      c.SynchronousQueue数据极少,不需要放队列
      这三种自上而下分别对应三种应用场景:数据量很大、不大、很少。

      d. PriorityBlockingQueue基于优先级的阻塞队列,重写comparable排序,无界队列。

      e.DelayQueue到延迟时间,才能从队列获取该元素。

 
二  线程设计模式
  1. future模式,类似ajax。比如用多个线程执行不同模块,以空间换时间,从而减少程序执行时间。
   举个例子main函数请求一方法发参数过去,那方法会启动一个线程去查数据,并告诉请求方先干别的吧,main函数调一方法接收返回结果时,这方法会wait,直到查到数据才被notify,然后返回结果。
   关键就是用了个wait、notify。   
  1. masterWorker模式,常用的并行计算模式。即系统由两类进程协作工作:master进程和worker进程。Master负责接受和分配任务,worker负责处理子任务。当各个Worker子进程处理完成后,会将结果返回给master,由master做归纳总结。其好处是能将一个大任务分解成若干小任务,并执行,从而提高系统的吞吐量。
  2. 生产-消费模式:生产者线程负责提交用户请求,消费者线程则负责处理生产者提交的任务,在生产者和消费者之间通过共享内存缓存区进行通信。
 
三  JDK多任务执行框架
Executor框架:在java.util.Concurrent下,是jdk并发包核心。比较重要的类:Executors,扮演线程工厂。通过Executors,可以创建特定功能的线程池。
Executors创建线程池方法:
  newFixedThreadPool(),固定线程数,池无空闲,任务就暂缓到任务队列。
  newSingleThreadExecutor(),一个线程的线程池,池无空闲,任务就暂缓到任务队列。

  newCachedThreadPool(),根据实际线程数随时调整池大小,无上限,无任务不创建线程,每个空闲线程60s后自动回收。

  newScheduledThreadPool(),返回SchededExecutorService对象,可指定线程数量。

  

Executors还提供一个可以自定义线程的方法:public ThreadPoolExecutor();  

  此自定义方法的构造方法对于队列是什么类型的比较关键:

  使用有界队列时,如果有新的任务需要执行,若线程池实际线程数小于corePoolSize,则优先创建线程,若大于corePoolSize,则会将任务加入队列,若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,若线程数大于maximumPoolSize,则执行拒绝策略。或其他自定义方式。

  使用无界的任务队列时:LinkedBlockingQueue。与有界队列相比,除非系统资源耗尽,否则无界的任务队列不存在任务入队失败的情况。当有新任务到来,系统的线程数小于corePoolSize时,则新建线程执行任务。当达到corePoolSize后,就不会继续增加。若后续仍有新的任务加入,而又没有空闲的线程资源,则任务直接进入队列等待。若任务创建和处理的速度差异很大,无界队列会保持快速增长,直到耗尽系统内存。
 
  附:spring定时器大都用spring Shedule,而不是spring quartz了。
 
 
四  Concurrent.util工具类
1、CyclicBarrier:等所有线程都准备好了一起出发。详见

2、CountDownLacth:监听初始化操作,初始化完毕,通知主线程继续工作。

3、Callable和Future使用:即Future模式,它非常适合处理很耗时、很长的业务逻辑,可减小系统响应时间,提高系统的吞吐量。

4、Semaphore信号量——java层面的限流。适合对系统高并发访问量进行评估:

  4.1  PV page view :页面浏览量,用户每刷新一次就会被记录一次。

  4.2  UV unique visitor:24小时内相同ip客户端只记录一次。

  4.3  QPS query per second:每秒查询数,可根据压力测试得到估值。

  4.4  RT response time:请求响应时间。

五 (重入锁、读写锁使用)锁的高级深化
  1. 重入锁:在需要进行同步的代码加上锁定。
  2. 读写锁:reentrantReadWriteLock,核心是实现读写分离的锁,在读多写少的高并发访问下,性能高于重入锁。
 
六  并发框架Disruptor
 
Disruptor它是一个开源的并发框架,并获得2011 Duke’s 程序框架创新奖,能够在无锁的情况下实现网络的Queue并发操作。
Disruptor是一个高性能的异步处理框架,或者可以认为是最快的消息框架(轻量的JMS),也可以认为是一个观察者模式的实现,或者事件监听模式的实现。
 
下载disruptor-3.3.2.jar引入我们的项目既可以开始disruptor之旅。
在使用之前,首先说明disruptor主要功能加以说明,你可以理解为他是一种高效的"生产者-消费者"模型。也就性能远远高于传统的BlockingQueue容器。
 
在Disruptor中,我们想实现hello world 需要如下几步骤:
  第一:建立一个Event类
  第二:建立一个工厂Event类,用于创建Event类实例对象
  第三:需要有一个监听事件类,用于处理数据(Event类)
  第四:我们需要进行测试代码编写。实例化Disruptor实例,配置一系列参数。然后我们对Disruptor实例绑定监听事件类,接受并处理数据。
  第五:在Disruptor中,真正存储数据的核心叫做RingBuffer,我们通过Disruptor实例拿到它,然后把数据生产出来,把数据加入到RingBuffer的实例对象中即可。

开发进阶系列:Java并发之从基础到框架的更多相关文章

  1. 【Xamarin开发 Android 系列 7】 Android 结构基础(下)

    原文:[Xamarin开发 Android 系列 7] Android 结构基础(下) *******前期我们不打算进行太深入的东西,省的吓跑刚进门的,感觉门槛高,so,我们一开始就是跑马灯一样,向前 ...

  2. 【Xamarin开发 Android 系列 6】 Android 结构基础(上)

    原文:[Xamarin开发 Android 系列 6] Android 结构基础(上) 前面大家已经熟悉了什么是Android,而且在 [Xamarin开发 Android 系列 4] Android ...

  3. 推荐扔物线的HenCoder Android 开发进阶系列 后期接着更新

    官网地址:http://hencoder.com/ 我来做一次辛勤的搬运工 HenCoder:给高级 Android 工程师的进阶手册 HenCoder Android 开发进阶: 自定义 View ...

  4. 当我们说线程安全时,到底在说什么——Java进阶系列(二)

    原创文章,同步发自作者个人博客,转载请以超链接形式在文章开头处注明出处http://www.jasongj.com/java/thread_safe/ 多线程编程中的三个核心概念 原子性 这一点,跟数 ...

  5. 【Xamarin开发 Android 系列 4】 Android 基础知识

    原文:[Xamarin开发 Android 系列 4] Android 基础知识 什么是Android? Android一词的本义指“机器人”,同时也是Google于2007年11月5日宣布的基于Li ...

  6. Java面试题系列 ----- Java基础面试题(91道)

    更多详情点击查看,点这里!这里!!这里!!! 文末获取所有面试PDF文档! Java概述 1. 何为编程 编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程. 为了 ...

  7. C#进阶系列——WebApi 身份认证解决方案:Basic基础认证

    前言:最近,讨论到数据库安全的问题,于是就引出了WebApi服务没有加任何验证的问题.也就是说,任何人只要知道了接口的url,都能够模拟http请求去访问我们的服务接口,从而去增删改查数据库,这后果想 ...

  8. Java开发知识之Java编程基础

    Java开发知识之Java编程基础 一丶Java的基础语法 每个语言都有自己的语法规范.例如C++ 入口点是main. 我们按照特定格式编写即可. Java也不例外. Java程序的语法规范就是 Ja ...

  9. mysql 开发进阶篇系列 55 权限与安全(安全事项 )

    一. 操作系统层面安全 对于数据库来说,安全很重要,本章将从操作系统和数据库两个层面对mysql的安全问题进行了解. 1. 严格控制操作系统账号和权限 在数据库服务器上要严格控制操作系统的账号和权限, ...

  10. mysql 开发进阶篇系列 47 物理备份与恢复(xtrabackup 的完全备份恢复,恢复后重启失败总结)

    一. 完全备份恢复说明 xtrabackup二进制文件有一个xtrabackup --copy-back选项,它将备份复制到服务器的datadir目录下.下面是通过 --target-dir 指定完全 ...

随机推荐

  1. NC20277 [SCOI2010]字符串

    题目链接 题目 题目描述 lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数.现在lxhg ...

  2. NC24727 [USACO 2010 Feb G]Slowing down

    题目链接 题目 题目描述 Every day each of Farmer John's N (1 <= N <= 100,000) cows conveniently numbered ...

  3. NC15128 老子的全排列呢

    题目链接 题目 题目描述 老李见和尚赢了自己的酒,但是自己还舍不得,所以就耍起了赖皮,对和尚说,光武不行,再来点文的,你给我说出来1-8的全排序,我就让你喝,这次绝不耍你,你能帮帮和尚么? 输入描述 ...

  4. Linux IOS镜像中查看Kernel 版本号

    开ISO镜像,到rpm包的目录里面去找到kernel-********.RPM这个包,中间的星号那一段就是内核版本

  5. Git合并固定分支的某一部分至当前分支

    在 Git 中,通常使用 git merge 命令来将一个分支的更改合并到另一个分支.如果你只想合并某个分支的一部分代码,可以使用以下两种方法: 1.批量文件合并 1.1.创建并切换到一个新的临时分支 ...

  6. win32 - 监控DNS是否发生改变

    两种方法: 第一种是使用WMI进行后台轮询 第二种是查询注册表对应的DNS键值 Here: HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameter ...

  7. zip压缩模块,tarfile压缩模块,包和模块,format格式化的复习--day17

    1.zipfile模块 import zipfile #导入模块 1.压缩文件 (1)创建压缩包 参数1压缩包名字,参数2以w模式创建,参数3压缩固定写法 zf = zipfile.ZipFile(& ...

  8. centos8.x阿里源配置

    >>> cd /etc/yum.repo.d >>> mkdir bak >>> mv *.repo bak/ >>> cd b ...

  9. 【Filament】Filament环境搭建

    1 前言 ​ Filament 是一个实时物理渲染引擎,用于 Android.iOS.Linux.macOS.Windows 和 WebGL 平台.该引擎旨在提供高效.实时的图形渲染,并被设计为在 A ...

  10. Springboot 撞上 NebulaGraph——NGbatis 初体验

    本文首发于 NebulaGraph 公众号 https://mp.weixin.qq.com/s/z56o6AEz1Z4RmS8Zdx6dTA 大家好,我是开源项目 NGbatis 的发起人大叶(Co ...