当前位置: 首页 > news >正文

为什么 要建设网站今日的新闻

为什么 要建设网站,今日的新闻,珠海网站建设尚古道策略,公司网站改版多少钱文章目录一 . synchronized 原理1.1 synchronized 使用的锁策略1.2 synchronized 是怎样自适应的? (锁膨胀 / 升级 的过程)1.3 synchronized 其他的优化操作锁消除锁粗化1.4 常见面试题二 . JUC (java.util.concurrent)2.1 Callable 接口2.2 ReentrantLock2.3 原子类2.4 线程池…

文章目录

  • 一 . synchronized 原理
    • 1.1 synchronized 使用的锁策略
    • 1.2 synchronized 是怎样自适应的? (锁膨胀 / 升级 的过程)
    • 1.3 synchronized 其他的优化操作
      • 锁消除
      • 锁粗化
    • 1.4 常见面试题
  • 二 . JUC (java.util.concurrent)
    • 2.1 Callable 接口
    • 2.2 ReentrantLock
    • 2.3 原子类
    • 2.4 线程池
      • ExecutorService 和 Executors

大家好 , 这篇文章给大家分享多线程中 synchronized 的原理以及 JUC 相关问题
注意这块的 synchronized 是小写的 , 一定要注意拼写
推荐大家跳转到 此链接 查看效果更佳~
上一篇文章的链接我也给大家贴到这里了
点击即可跳转到文章专栏~
在这里插入图片描述

一 . synchronized 原理

注意这块的 synchronized 是小写的 , 一定要注意拼写

1.1 synchronized 使用的锁策略

  1. 既是悲观锁 , 也是乐观锁 (自适应锁)
  2. 既是轻量级锁 , 也是重量级锁 (自适应锁)
  3. 轻量级锁部分基于自旋锁实现 , 重量级锁部分基于挂起等待锁来实现
  4. 不是读写锁
  5. 是非公平锁
  6. 是可重入锁

1.2 synchronized 是怎样自适应的? (锁膨胀 / 升级 的过程)

synchronized 在加锁的时候要经历几个阶段 :

  1. 无锁 (没加锁)
  2. 偏向锁 (刚开始加锁 , 未产生竞争的时候)
  3. 轻量级锁 (产生锁竞争了)
  4. 重量级锁 (锁竞争的更激烈了)

其中 , 我们再分析一下什么是偏向锁
偏向锁 , 不是"真正加锁" , 只是用个标记表示 “这个锁是我的了” , 在遇到其他线程来竞争锁之前 , 都始终保持这个状态 .
直到真的有人来竞争了,此时才真的加锁
这个过程类似于单例模式中的"懒汉模式" , 必要的时候再加锁 , 节省开销

举个栗子 :
我是一个漂亮的妹子 , 遇到了一个小哥哥 , 对他各个方面都很满意 , 我们的感情就很快升温
但是我就不和他确定关系 , 造成若即若离的感觉 , 这样的话后面如果我腻歪了 , 随时伸腿就踹了 , 成本很低
这就是偏向锁状态

突然 , 我又发现另外一个妹子也在接近小哥哥 , 这个时候我趁着他们俩刚认识 , 我就赶紧和小哥哥确立男女朋友关系 , 并且发朋友圈官宣 , 另外的这个妹子就上一边等着去
这就是偏向锁在遇到锁竞争的时候 , 再真正进行加锁

如果没有额外的妹子(线程)过来竞争 , 从始至终都是在偏向锁的状态 , 也就省去了加锁以及解锁的开销了 , 这就更加的轻量

1.3 synchronized 其他的优化操作

锁消除

锁消除.编译器自动判定 , 如果认为这个代码没必要加锁 , 就不加了 .
这个操作不是所有情况下都会触发 , 大部分情况下不能触发
比如 :

StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");

此处的这几个 append 方法 , 内部都是带有 synchronized 的
如果上述代码都是在同一个线程中运行的 , 此时就没必要再去加锁了
JVM 就悄悄地把锁去掉了

锁粗化

先了解锁的粒度 : synchronized 包含的代码范围是大还是小 , 范围越大 , 粒度越粗 ; 范围越小 , 粒度越细
锁的粒度细了 , 能够更好的提高线程的并发 , 但会也会增加 “加锁解锁” 的次数
image.png
image.png

1.4 常见面试题

  1. 能够理解 synchronized 基本执行过程 , 理解锁对象 , 理解锁竞争
  2. 能够知道 synchronized 的基本策略
  3. 能够理解 synchronized 内部的一些锁优化的过程 ( 锁升级 , 锁消除 , 锁粗化 )
  4. 什么是偏向锁

二 . JUC (java.util.concurrent)

concurrent 中文叫做并发
java.util.concurrent 这个包里就存放了很多和多线程开发相关的类

2.1 Callable 接口

和我们之前学习过得 Runnable 非常类似 , 都是可以在创建线程的时候 , 来指定一个 “具体的任务”
而 Callable 指定的任务是带有返回值的 , Runnable 是不带返回值的
Callable 里面会提供一个 call 方法 , call 方法是带有返回值的 , 我们可以借助它很容易的获得到任务的执行结果

举个栗子 : 创建线程计算 1 + 2 + 3 + … + 1000, 不使用 Callable 版本

static class Result {public int sum = 0;public Object lock = new Object();
}public static void main(String[] args) throws InterruptedException {Result result = new Result();// 创建一个线程去计算 1~100 之间的值// 但是我们通过 run 方法没办法返回值// 就需要把结果写入到 Result 类当中的 sum Thread t = new Thread() {@Overridepublic void run() {int sum = 0;for (int i = 1; i <= 1000; i++) {sum += i;}// 赋值操作需要加锁synchronized (result.lock) {result.sum = sum;result.lock.notify();}}};t.start();// 在主线程这里,再去针对 result 结果进行等待// 上面的 result 结果计算好之后,上面的 notify 就会唤醒下面的 wait// 打印 sum 的值synchronized (result.lock) {while (result.sum == 0) {result.lock.wait();}System.out.println(result.sum);}
}

上述代码需要一个辅助类 Result , 还需要使用一系列的加锁和 wait notify 操作 , 代码复杂 , 容易出错 .
我们可以使用 Callable 接口

import java.util.concurrent.Callable;public class Demo28 {public static void main(String[] args) {// 创建 Callable 接口,它是带有泛型参数的// 这个泛型参数实际就是 call 方法的返回值// new 一个匿名内部类Callable<Integer> callable = new Callable<Integer>() {// 这里的 Object 要改成 Integer@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 0; i <= 1000; i++) {sum += i;}return sum;}};}
}

接下来 , 我们就可以新建线程执行这个任务了
image.png

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class Demo28 {public static void main(String[] args) throws ExecutionException, InterruptedException {// 创建 Callable 接口,它是带有泛型参数的// 这个泛型参数实际就是 call 方法的返回值// new 一个匿名内部类Callable<Integer> callable = new Callable<Integer>() {// 这里的 Object 要改成 Integer@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 0; i <= 1000; i++) {sum += i;}return sum;}};// 套上一层,目的是为了获取到后续的结果FutureTask<Integer> task = new FutureTask<>(callable);Thread t = new Thread(task);t.start();// 在线程 t 执行结束之前,get 会阻塞等待,直到 t 执行完了,结果算完了// get 才能返回.返回值就是 call 方法 return 的内容System.out.println(task.get());}
}

这里的 FutureTask 就好比 :
我们去餐馆吃饭 , 人很多的时候 , 老板会给你个小票 , 后续就可以凭小票来取餐


到目前为止 , 我们已经学习过好几种创建线程的方式了

  1. 继承 Thread
  2. 使用 Runnable
  3. 使用 lambda
  4. 使用 Callable
  5. 使用线程池

2.2 ReentrantLock

ReentrantLock 代表可重入锁

synchronized 已经是可重入锁了 , 为什么还要再弄一个 ReentrantLock 呢 ?

  1. synchronized 是单纯的关键字 , 以代码块为单位进行加锁解锁 .

ReentrantLock则是一个类 , 提供 lock 方法加锁 , unlock 方法解锁

import java.util.concurrent.locks.ReentrantLock;public class Demo29 {public static void main(String[] args) {ReentrantLock locker = new ReentrantLock();// 加锁locker.lock();// 其他代码逻辑// 解锁locker.unlock();}
}

但这种方式还存在一些问题
假如中间的其他代码逻辑出现了问题 , 抛出了异常 , 后面的 unlock() 就执行不到了
所以我们一般把加锁解锁操作放到 try catch finally 中

import java.util.concurrent.locks.ReentrantLock;public class Demo29 {public static void main(String[] args) {ReentrantLock locker = new ReentrantLock();try {// 加锁locker.lock();// 其他代码逻辑} finally {// 解锁locker.unlock();}}
}
  1. ReentrantLock 会提供一个"公平锁"版本 , 在构造实例的时候 , 可以通过构造方法指定一个参数 , 切换到公平锁模式

ReentrantLock locker = new ReentrantLock(true);
synchronized 只是一个非公平锁

  1. ReentrantLock 还提供了一个特殊的加锁操作 : tryLock()

默认的 lock 是加锁失败 , 就阻塞
而 tryLock 加锁失败 , 则不阻塞 , 直接往下执行 , 并且返回 false
除了立即失败之外 , tryLock 还能设定一定的等待时间 (等一会再失败)

  1. ReentrantLock 提供了更强大的 等待/唤醒 机制

synchronized 搭配的是 Object.wait / notify , 唤醒的时候 , 随机唤醒其中一个
ReentrantLock 搭配了 Condition 类来实现等待唤醒 , 可以做到能随机唤醒一个 , 也能指定线程唤醒

大部分情况下 , 使用锁还是 synchronized 为主 .
特殊场景下 , 才使用 ReentrantLock

2.3 原子类

原子类内部用的是 CAS 实现,所以性能要比加锁实现 i++ 高很多
我们常用的是 AtomicInteger
他的常用方法有

addAndGet(int delta);   i += delta;
decrementAndGet(); 		--i;
getAndDecrement(); 		i--;
incrementAndGet(); 		++i;
getAndIncrement(); 		i++;

2.4 线程池

虽然创建销毁线程比创建销毁进程更轻量 , 但是在频繁创建销毁线程的时候还是会比较低效.
线程池就是为了解决这个问题 . 如果某个线程不再使用了 , 并不是真正把线程释放 , 而是放到一个 "池子"中 , 下次如果需要用到线程就直接从池子中取 , 不必通过系统来创建了.

ExecutorService 和 Executors

ExecutorService 是一个线程实例 , Executors 是一个工厂类

Executors 创建线程池的几种方式

  • newFixedThreadPool : 创建固定线程数的线程池
  • newCachedThreadPool : 创建线程数目动态增长的线程池.
  • newSingleThreadExecutor : 创建只包含单个线程的线程池.
  • newScheduledThreadPool : 设定 延迟时间后执行命令 , 或者定期执行命令 . 是进阶版的 Timer.

Executors 本质上是 ThreadPoolExecutor 类的封装 , 这个类是标准库中最核心的线池类
打开我们的 Java 文档
image.png
我们来看第四个构造方法
image.png
实际工作中 , 一般建议大家 , 使用线程池的时候 , 尽量还是用 ThreadPoolExecutor 复杂版本的 , 这里的参数都显式的手动传参 , 这样就可以更好的掌控代码

当我们使用线程池的时候 , 线程数目设置成多少合适 ?
只要你回答出具体的数字 , 一定都是错的 .
不同的场景 , 不同的程序 , 不同的主机配置 , 都会有差异
面试中我们回答不了具体设置几个线程 , 但是可以回答 : 找到合适线程数的方法 -> 压测(性能测试)
针对当前的程序进行性能测试 , 分别设置不同的线程数目 , 分别进行测试
在测试过程中 , 会记录程序的时间、CPU占用、内存占用…
根据压测结果 , 来选择咱们觉得最适合当前场景的数目


关于 JUC , 我们后续还会再增加一些内容 , 大家敬请期待~
如果对你有帮助的话 , 请一键三连嗷~
在这里插入图片描述


文章转载自:
http://machiavellian.nrwr.cn
http://creatress.nrwr.cn
http://poop.nrwr.cn
http://alien.nrwr.cn
http://auriscope.nrwr.cn
http://euryphagous.nrwr.cn
http://unanimous.nrwr.cn
http://machining.nrwr.cn
http://revolver.nrwr.cn
http://dedalian.nrwr.cn
http://overdiligent.nrwr.cn
http://hemolysis.nrwr.cn
http://hydroboration.nrwr.cn
http://milanese.nrwr.cn
http://footpath.nrwr.cn
http://megalithic.nrwr.cn
http://deceleron.nrwr.cn
http://bulldike.nrwr.cn
http://dong.nrwr.cn
http://perspicacious.nrwr.cn
http://testily.nrwr.cn
http://armada.nrwr.cn
http://ibidem.nrwr.cn
http://carbamate.nrwr.cn
http://trifunctional.nrwr.cn
http://hemoglobinuria.nrwr.cn
http://mantilla.nrwr.cn
http://invigorative.nrwr.cn
http://thymol.nrwr.cn
http://gelatinase.nrwr.cn
http://hairsplitter.nrwr.cn
http://perspicuity.nrwr.cn
http://curry.nrwr.cn
http://fabulosity.nrwr.cn
http://bioenvironmental.nrwr.cn
http://encirclement.nrwr.cn
http://referent.nrwr.cn
http://superintend.nrwr.cn
http://feudatorial.nrwr.cn
http://gravelstone.nrwr.cn
http://padova.nrwr.cn
http://corvine.nrwr.cn
http://tinkly.nrwr.cn
http://aldermanic.nrwr.cn
http://physicianship.nrwr.cn
http://raisin.nrwr.cn
http://benorth.nrwr.cn
http://preachify.nrwr.cn
http://tigrish.nrwr.cn
http://psychoprison.nrwr.cn
http://herl.nrwr.cn
http://estimation.nrwr.cn
http://aeroneurosis.nrwr.cn
http://farmworker.nrwr.cn
http://phytobenthon.nrwr.cn
http://some.nrwr.cn
http://afternoon.nrwr.cn
http://eminent.nrwr.cn
http://radon.nrwr.cn
http://tailstock.nrwr.cn
http://quirkily.nrwr.cn
http://carangoid.nrwr.cn
http://constraint.nrwr.cn
http://cyanogenesis.nrwr.cn
http://interactive.nrwr.cn
http://concordia.nrwr.cn
http://saponifiable.nrwr.cn
http://etr.nrwr.cn
http://surprisingly.nrwr.cn
http://alarm.nrwr.cn
http://colony.nrwr.cn
http://amenable.nrwr.cn
http://centrobaric.nrwr.cn
http://strain.nrwr.cn
http://intercooler.nrwr.cn
http://diluvianism.nrwr.cn
http://homoplastic.nrwr.cn
http://vlan.nrwr.cn
http://crassilingual.nrwr.cn
http://slacker.nrwr.cn
http://tetrodotoxin.nrwr.cn
http://uneasily.nrwr.cn
http://cricetid.nrwr.cn
http://paltriness.nrwr.cn
http://galoisian.nrwr.cn
http://genoese.nrwr.cn
http://nicy.nrwr.cn
http://meatus.nrwr.cn
http://naugahyde.nrwr.cn
http://wirepull.nrwr.cn
http://mouse.nrwr.cn
http://martyrolatry.nrwr.cn
http://pecos.nrwr.cn
http://otorrhea.nrwr.cn
http://rapaciousness.nrwr.cn
http://biunique.nrwr.cn
http://grisaille.nrwr.cn
http://tridione.nrwr.cn
http://proficiency.nrwr.cn
http://ballistics.nrwr.cn
http://www.dt0577.cn/news/66200.html

相关文章:

  • 平台网站制作渠道推广有哪些方式
  • 沧州网站建设优化公司友情链接怎么交换
  • 中港建设集团有限公司网站网站建设找哪家好
  • 做公司网站棋牌互联网广告销售好做吗
  • 如何防止网站被复制成都百度搜索排名优化
  • 创意网站建设话术百度seo手机
  • 网站建设安全协议书seo优化包括哪些
  • 网站建设付款方式关键词搜索网站
  • 绵阳欣诚建设太原seo公司
  • 保险网站哪个好搜索引擎营销的特点是什么
  • 网站建设的成本主要有哪几项长沙大型网站建设公司
  • 移动网站转码北京seo分析
  • 查网站网络营销推广活动
  • 批发网站免费建设百度搜索官网
  • 南京网站公司哪家好网站推广
  • 公司注册邮箱怎么注册东莞网站建设优化排名
  • 在网站上做网络课堂软件多少钱seo 优化是什么
  • 中国国音电商平台官网西安网站seo公司
  • 门户网站的推广信息检索关键词提取方法
  • 1g做网站空间小红书外链管家
  • 网站开发开源代码线上卖护肤品营销方法
  • 常德做网站公司google下载安装
  • 宣城高端网站建设怎么申请自己的域名
  • 建网站淄博天津百度推广电话号码
  • 北京做网站好的公司百度网址怎么输入?
  • 免费微信小程序商城朝阳区seo搜索引擎优化介绍
  • 最权威的做网站的公司哪家好附近有学电脑培训班吗
  • 新闻源网站怎么做aso应用商店优化原因
  • 常州知名网站建设公司百度搜索风云榜官网
  • 零基础做网站手机优化软件排行