一  线程基础
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. 【开工大吉】推荐4款开源、美观的WPF UI组件库

    前言 经常有小伙伴在技术群里提问:WPF有什么好用的UI组件库?,今天大姚给大家推荐4款开源.美观的WPF UI组件库. WPF介绍 WPF 是一个强大的桌面应用程序框架,用于构建具有丰富用户界面的 ...

  2. react 新旧生命周期有什么区别?新增了哪些钩子?废弃了哪些钩子?为什么废弃?

    壹 ❀ 引 在日常面试中,若对于了解react的同学而言,多多少少会被问到生命周期相关的问题,比如大致阐述生命周期的运作流程,以及每个钩子函数大致的作用,而我在两位出去面试的同事那里了解到,他们都遇到 ...

  3. The Missing Semester - 第五讲 学习笔记

    第五讲 命令行环境 课程视频地址:https://www.bilibili.com/video/BV1Dy4y1a7BW 课程讲义地址:https://missing-semester-cn.gith ...

  4. mysql 外键索引入门介绍,为什么工作中很少有人使用?

    背景 以前工作学习中,一直被告诫不要使用外键,所以也没有仔细整理过. 这里记录一下笔记. 外键 是什么? MySQL 的外键(Foreign Key)是一种关系型数据库中用于建立表与表之间关联关系的重 ...

  5. 基于 junit5 实现 junitperf 源码分析

    前言 上一节介绍了基于 junit4 实现 junitperf,但是可以发现定义变量的方式依然不够优雅. 那可以让用户使用起来更加自然一些吗? 有的,junit5 为我们带来了更加强大的功能. 拓展阅 ...

  6. Java集合框架学习(八) HashMap详解

    HashMap介绍 HashMap是一个基于Map的集合类,用于存储Key和Value的键值对. 通常用HashMap<Key, Value> or HashMap<K, V> ...

  7. python3调用nmap封装

    python3调用nmap封装; 外部处理好参数后直接调用; #!/usr/bin/env python # -*- coding: utf-8 -*- """ 代码修改 ...

  8. CentOS8安装Docker报错问题解决

    问题描述 CentOS版本:8.5.2111. # cat /etc/redhat-release CentOS Linux release 8.5.2111 安装准备: # 安装所需软件包 sudo ...

  9. 【LeetCode数组#5行为模拟】螺旋矩阵II+I

    螺旋矩阵II 力扣题目链接(opens new window) 给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵. 示例: 输入: 3 输出: [ [ ...

  10. 【Azure Redis 缓存】Azure Redis 功能性讨论三: 调优参数配置

    问题描述 在使用Azure Redis的服务中,遇见了以下系列问题需要澄清: 在开源Redis 6.0 中,多线程默认禁用,只使用主线程.如需开启需要修改redis.config配置文件.Redis的 ...