Java JUC

1.Java JUC简介

  • 在Java5.0提供了java.uti.concurrent(简称JUC)包,在词此包中增加了在并发编程中很常用的实用工具类,用于定义类似于线程的自定义子系统,包括线程池、异步IO和轻量级任务框架。提供可调用的、灵活的线程池。还提供了设计用于多线程上下文中的Collection实现等

1-volatile关键字

内存可见性

  • 内存可见性(Memory Visibility)是指当某个线程正在使用对象状态而另一个线程在同时修改该状态,需要确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化。
  • 可见性错误是指当读操作与写操作在不同的线程中执行时,我们无发确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情。
  • 我们可以通过同步来保证对象被安全地发布。除此之外我们也可以使用更加轻量级地volatile变量。

volatile 关键字

  • Java提供了一种削弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。可以将volatile看作一个轻量级的锁,但是又与锁有些不同:
    • 对于多线程,不是一种互斥关系
    • 不能保证变量状态的“原子性操作”
   
   /**
 * 一、volatile 关键字:当多个线程进行操作共享数据时,可以保证内存中的数据可见。
 *                      相较于synchronized是一种较为轻量级的同步策略。
 *  注意:
 *  1.volatile 不具备“互斥性”
 *  2.volatile 不能保证变量的“原子性”
 */
public class TestVolatile {
    public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        new Thread(td).start();

        while (true){
            if(td.isFlag()){
                System.out.println("----------------------");
                break;
            }
        }
    }

}

class ThreadDemo implements Runnable{

    private volatile boolean flag = false;

    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
        }
        flag = true;
        System.out.println("flag="+isFlag());
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

2-原子变量CAS算法

CAS算法

  • CAS(Compare-And-Swap)是一种硬件对并发的支持,针对多处理器操作而设计的处理器中的一种特殊指令,用于管理对共享数据的并发访问。
  • CAS 是一种无锁的非阻塞算法的实现。
  • CAS包含了3个操作数:
    - 需要读写的内存值V
    - 进行比较的值 A
    - 拟写入的新值 B
  • 当且仅当V的值等于A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作i。

原子变量

  • 类的小工具包,支持在单个变量上解除锁的线程安全编程。事实上,此包中的类可将 volatile 值、字段和数组元素的概念扩展到那些也提供原子条件更新操作的类。
  • 类AtomicBoolean、AtomicInteger、AtomicLong和AtomicReference的实例各自提供对相应类型单个变量的访问和更新。每个类也为该类型提供适当的实用工具方法。
  • AtomicIntegerArray、AtomicLongArray和AtomicReferenceArray类进一步扩展了元组操作,对这些类型的数组提供了支持。这些类在为其数组元素提供volatile访问语义方面也引人注目,这对于普通数组来说是不受支持的。
  • 核心方法:boolean compareAndSet(expectedValue,updateValue)
  • java.util.concurrent.atomic包下提供了一些原子操作的常用类:
    • AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference
    • AtomicIntegerArray、AtomicLongArray
    • AtomicMarkableReference
    • AtomicReferenceArray
    • AtomicStampedReference

3-ConcurrentHashMap锁分段机制

ConcurrentHashMap

  • java 5.0在java.util.concurrent包中提供了多种并发容器类带来改进同步容器的性能。
  • ConcurrentHashMap 同步容器类是java5增加的一个线程安全的哈希表。对于多线程的操作,介于HashMap与Hashtable之间。内部采用“锁分段”机制替代Hashtale的独立锁。进而提高性能。
  • 此包还提供了设计用于多线程上下文中的Collection实现:
    ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet、
    CopyOnWriteArrayList和CopyOnWriteArraySet。当期望许多线程访问一个给定collection时,ConcurrentHashMap通常优于同步的HashMap,ConcurrentSkipListMap通常优于同步的TreeMap。当期望的读数和便利远远大于列表的更新数时,CopyOnWriteArrayList优于同步的ArrayList。

4-CountDownlatch闭锁

CountDownlatch

  • Java 5.0 在 java.util.concurrent包中提供了多种并发容器类来改进同步容器的性能。
  • CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,他允许一个或多个线程一直等待。
  • 闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完成才继续执行:
    • 确保某个计算在其需要的所有资源都被初始化之后才仅需执行;
    • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动;
    • 等待直到某个操作所有参与者都准备就绪再继续执行。

5-实现Callable接口

Callable接口

  • java 5.0在java.util.concurrent提供了一个新的创建执行线程的方式:Callable接口
  • Callable接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的,但是Runnable不会返回结果,并且无法抛出经过检查的异常。
  • Callable需要依赖FutureTask,FutureTask也可以用作闭锁。

6-Lock同步锁

显示锁Lock

  • 在java 5.0 之前,协调共享对象的访问时可以使用的机制只有sychronized和volatile。java5.0后增加了一些新的机制,但并不是一种替代的内置锁的方法,而是当内值锁不适用时,作为一种可选择的高级功能。
  • ReentrantLock 实现了Lock接口,并提供了与synchronized相同的互斥性和内存可见性。但相较于sychronized 提供了更高的处理锁的灵活性。

7-Condition控制线程通信

Condition

  • Condition接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用Object.wait访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个Lock可能与多个Condition对象关联,为了避免兼容性问题,Condition方法的名称与对应的Object版本中的不同。
  • 在Condition对象中,与wait、notify和notifyAll方法对应得分别是await、signal和sinalAll。
  • Condition 实例实质上被绑定到一个锁上。要为特定Lock实例获得Condition实例,请使用其newCondition()方法。

8-线程按需交替

线程按序交替
-编写一个程序,开启 3 个线程,这三个线程的 ID 分别为A、 B、 C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。
如: ABCABCABC…… 依次递归

9-ReadWriteLock读写锁

读-写锁ReadWriteLock

  • ReadWriteLock维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有writer,读取所可以由多个reader线程同时保持。写入锁是独占的。。
  • ReadWriteLock读取操作通常不会改变共享资源,但执行写入操作时,必须独占方式来获取锁。对于读取操作占多数的数据结构。ReadWriteLock能提供比独占锁更高的并发性。而对于只读的数据结构,其中包含的不变性可以完全不需要考虑加锁操作。
/*
 * 1. ReadWriteLock : 读写锁
 * 
 * 写写/读写 需要“互斥”
 * 读读 不需要互斥
 * 
 */
public class TestReadWriteLock {

	public static void main(String[] args) {
		ReadWriteLockDemo rw = new ReadWriteLockDemo();
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				rw.set((int)(Math.random() * 101));
			}
		}, "Write:").start();
		
		
		for (int i = 0; i < 100; i++) {
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					rw.get();
				}
			}).start();
		}
	}
	
}

class ReadWriteLockDemo{
	
	private int number = 0;
	
	private ReadWriteLock lock = new ReentrantReadWriteLock();
	
	//读
	public void get(){
		lock.readLock().lock(); //上锁
		
		try{
			System.out.println(Thread.currentThread().getName() + " : " + number);
		}finally{
			lock.readLock().unlock(); //释放锁
		}
	}
	
	//写
	public void set(int number){
		lock.writeLock().lock();
		
		try{
			System.out.println(Thread.currentThread().getName());
			this.number = number;
		}finally{
			lock.writeLock().unlock();
		}
	}
}

10-线程八锁

线程八锁

  • 一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程调用其中的一个sychronized方法了,其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一一个线程去访问这些sychronized方法
  • 锁的是当前对象this,被锁定后,其他的线程都不能进入到当前对象的其他的sychronized方法
  • 加个普通方法后发现和同步锁无关
  • 换成两个对象后,不是同一把锁了,情况立刻变化。
  • 都换成静态同步方法后,情况又变化。
  • 所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。
  • 所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!

11-线程池

线程池

  • 第四种获取线程的方法:线程池,一个ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用Executors工厂方法配置
  • 线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法。每个ThreadPoolExcutor还维护着一些基本的统计数据,如完成的任务数。
  • 为了便于跨大量上下文的使用,此类提供了很多可调整的参数和扩展的钩子(hook)。但是,强烈建议程序员使用较为方便的Excutors工厂方法:
    • Excutors.newCachedThreadPool()(无界限程池,可以进行自动线程回收)
    • Excutors.newFixedThreadPool(int)(固定大小线程池)
    • Excutors.newSingleThreadExcutor()(单个后台线程)
      它们均为大多数使用场景预定义了设置。

12-线程调度

ScheduledExcutorService

  • 一个ExecutorService,可安排在给定的延迟后运行或定期执行的命令。

13-ForkJoinPool分支/合并框架 工作窃取

                          Fork/Join框架
  • Fork/Join框架:就是在比要的情况下,将一个大任务,进行差分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行join汇总。
    在这里插入图片描述

Fork/Join框架与线程池的区别

  • 采用“工作窃取”模式(work-stealing)
    当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。
  • 相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上,在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态。而在fork/join框架实现中,如果某个子问题由于等待另一个子问题的完成而无法继续运行。那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行,这种方式减少了线程的等待时间,提高了性能。

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 全新的界面设计 ,将会带来全新的写作体验;
  2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
  3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  4. 全新的 KaTeX数学公式 语法;
  5. 增加了支持甘特图的mermaid语法1 功能;
  6. 增加了 多屏幕编辑 Markdown文章功能;
  7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  8. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
查找:Ctrl/Command + F
替换:Ctrl/Command + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片: Alt

带尺寸的图片: Alt

居中的图片: Alt

居中并且带尺寸的图片: Alt

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目Value
电脑$1600
手机$12
导管$1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列第二列第三列
第一列文本居中第二列文本居右第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPEASCIIHTML
Single backticks'Isn't this fun?'‘Isn’t this fun?’
Quotes"Isn't this fun?"“Isn’t this fun?”
Dashes-- is en-dash, --- is em-dash– is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。2

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n1)!nN 是通过欧拉积分

Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.

你可以找到更多关于的信息 LaTeX 数学表达式here.

新的甘特图功能,丰富你的文章

Mon 06 Mon 13 Mon 20 已完成 进行中 计划一 计划二 现有任务 Adding GANTT diagram functionality to mermaid
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

Created with Raphaël 2.2.0 开始 我的操作 确认? 结束 yes no
  • 关于 Flowchart流程图 语法,参考 这儿.

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值