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

优创智汇高端网站建设电话怎么样北京模板建站哪家好

优创智汇高端网站建设电话怎么样,北京模板建站哪家好,阿里云备案域名出售,怎么更新网站内容目录 1、Future 1.1、Callable和Runnable的不同 1.2、Future的主要功能 1.3、常用方法 1.4、Future使用注意事项 1.5、CompletableFuture(旅游平台问题) 1.5.1、需求 1.5.2、解决方案1#xff1a;串行 1.5.3、解决方案2#xff1a;线程池 1.5.4、解决方案3#xf…目录 1、Future 1.1、Callable和Runnable的不同 1.2、Future的主要功能 1.3、常用方法 1.4、Future使用注意事项 1.5、CompletableFuture(旅游平台问题) 1.5.1、需求 1.5.2、解决方案1串行 1.5.3、解决方案2线程池 1.5.4、解决方案3CountDownLatch 1.5.4、解决方案4CompletableFuture推荐 2、线程协作 2.1、信号量 2.2、CountDownLatch闭锁 2.2.1、场景一一个线程等待多个线程 2.2.2、场景二多个线程等待一个线程 2.3、CyclicBarrier栅栏 2.3.1、原理 2.3.2、构造函数 2.3.3、CyclicBarrier和CountDownLatch的区别 3、Java内存模型 3.1、Java内存模型JMM 3.2、指令重排序 3.3、Java原子操作的注意事项 3.3.1、Java中的原子操作 3.3.2、long和double的原子性 3.4、内存可见性 3.5、主内存和工作内存的关系 3.6、happens-before原则 3.6.1、定义 3.6.2、规则 3.7、volatile作用 3.8、单例模式的双重检查锁模式 3.8.1、实现代码 3.8.2、实体对象为什么要加volatile 4、CAS原理 4.1、CAS是什么 4.2、优点 4.3、CAS应用场景 4.4、CAS导致的问题 5、死锁问题 5.1、定义 5.2、条件 5.3、命令行定位死锁(jstack) 5.4、如何解决死锁 5.4.1、线上死锁 5.4.2、避免死锁 5.4.3、检测与恢复策略(先允许系统发生死锁然后再解除) 5.4.4、鸵鸟策略 6、final关键字和不变性 6.1、用法 6.2、为什么String被设计成不可变的 7、AQS框架 7.1、原理 7.2、线程协同工具类(AQS实现) 1、Future 1.1、Callable和Runnable的不同 Callable有返回对象(Future)可以抛出受检异常需实现call方法。Runnable无返回值不能抛出受检异常需实现run方法。 1.2、Future的主要功能 通过 Future 可以了解任务执行情况或者取消任务的执行还可获取任务执行的结果。 1.3、常用方法 get()获取任务的执行结果。任务已经结束get()方法直接返回执行结果         任务未开始或运行中get()方法会阻塞当前线程         任务抛出异常get()方法会抛出ExecutionException异常         任务被取消get()方法会抛出CancellationException异常         任务超时get()方法会抛出TimeoutException异常。 isDone()判断当前任务是否执行完毕。成功执行和异常情况都会返回true。 cancle()取消任务执行。任务还未开始                 调用cancle()任务取消返回true。         任务已经完成或已经被取消                 调用cancle()取消失败返回false。         任务正在执行                 调用cancle(boolean mayInterruptIfRunning)                 mayInterruptIfRunning true执行任务的线程就会收到一个中断的信号正在执行的任务可能会有一些处理中断的逻辑进而停止。                 mayInterruptIfRunning false代表不中断正在运行的任务也就是说本次 cancel 不会有任何效果同时 cancel 方法会返回 false。 isCancelled判断能否被取消。 1.4、Future使用注意事项 当 for 循环批量获取 Future 的结果时容易 blockget 方法调用时应使用 timeout 限制。带超时参数的 get(long timeout, TimeUnit unit) 方法。如果在限定的时间内没能返回结果的话那么便会抛出一个 TimeoutException 异常随后就可以把这个异常捕获住或者是再往上抛出去这样就不会一直卡着了。Future 的生命周期不能后退Future 并没有产生新的线程。在把 Callable 提交到线程池后真正执行 Callable 的其实还是线程池中的线程而线程池中的线程是由 ThreadFactory 产生的这里产生的新线程与 Callable、Future 都没有关系所以 Future 并没有产生新的线程。 1.5、CompletableFuture(旅游平台问题) 1.5.1、需求 需要获取各航空公司的机票信息汇总后展示给用户。 1.5.2、解决方案1串行 串行获取耗时多不可取。 1.5.3、解决方案2线程池 线程池并行获取必须等待3s。 1.5.4、解决方案3CountDownLatch CountDownLatch并行获取。 1.5.4、解决方案4CompletableFuture推荐 2、线程协作 2.1、信号量 作用控制那些需要限制并发访问量的资源。 原理信号量会维护“许可证”的计数而线程去访问共享资源前必须先拿到许可证。线程可以从信号量中去“获取”一个许可证一旦线程获取之后信号量持有的许可证就转移过去了所以信号量手中剩余的许可证要减一。 示例主要方法Semaphore(int permits, boolean fair)初始化许可证                 第一个参数是许可证的数量另一个参数是是否公平。         acquire()获取许可证可响应中断。         acquireUninterruptibly()    获取许可证不可响应中断。         release()释放许可证。 注意事项获取和释放的许可证数量尽量保持一致         信号量支持跨线程、跨线程池。         合理的情况下可由线程A获取线程B释放。 信号量能被 FixedThreadPool 替代吗不能。考虑如下场景         在调用慢服务之前需要有个判断条件比如只想在每天的零点附近去访问这个慢服务时受到最大线程数的限制比如 3 个线程而在除了每天零点附近的其他大部分时间我们是希望让更多的线程去访问的。所以在这种情况下就应该把线程池的线程数量设置为 50 甚至更多然后在执行之前加一个 if 判断如果符合时间限制了比如零点附近再用信号量去额外限制这样做是比较合理的。 2.2、CountDownLatch闭锁 CountDownLatch不能重用。 2.2.1、场景一一个线程等待多个线程 一个线程等待其他多个线程执行完毕才会继续往下执行。在主线程里await()在任务线程里countDown()。 public static void main(String[] args) throws InterruptedException {CountDownLatch latch  new CountDownLatch(5);ExecutorService service  Executors.newFixedThreadPool(5);for (int i  0; i  5; i) {final int no  i  1;Runnable runnable  new Runnable() {Overridepublic void run() {try {Thread.sleep((long) (Math.random() * 10000));System.out.println(no  号运动员完成了比赛。);} catch (InterruptedException e) {e.printStackTrace();} finally {latch.countDown();}}};service.submit(runnable);}System.out.println(等待5个运动员都跑完.....);latch.await();System.out.println(所有人都跑完了比赛结束。);} 2.2.2、场景二多个线程等待一个线程 多个线程等待某一个线程的信息同时开始执行。在主线程countDown()在任务线程里await()。 public static void main(String[] args) throws InterruptedException {System.out.println(运动员有5秒的准备时间);CountDownLatch countDownLatch  new CountDownLatch(1);ExecutorService service  Executors.newFixedThreadPool(5);for (int i  0; i  5; i) {final int no  i  1;Runnable runnable  new Runnable() {Overridepublic void run() {System.out.println(no  号运动员准备完毕等待裁判员的发令枪);try {countDownLatch.await();System.out.println(no  号运动员开始跑步了);} catch (InterruptedException e) {e.printStackTrace();}}};service.submit(runnable);}Thread.sleep(5000);System.out.println(5秒准备时间已过发令枪响比赛开始);countDownLatch.countDown();} 2.3、CyclicBarrier栅栏 2.3.1、原理 内部有一个正数计数器初始化时指定一个正数每当有一个线程使用await()方法时计数器加1当前线程阻塞直到计数器的值为初始化的正数时打开栅栏。 2.3.2、构造函数 CyclicBarrier(int parties)指定一个正整数parties在线程中调用await()阻塞当前线程         当有parties个线程都调用await()时唤醒之前阻塞的所有线程继续往下执行。 CyclicBarrier(int parties, Runnable barrierAction)parties等待的线程数         barrierAction预定数量的线程数到达后需要执行的操作 2.3.3、CyclicBarrier和CountDownLatch的区别 相同点都能阻塞一个或一组线程直到某个预设的条件达成发生再统一出发。 不同点作用对象不同                 CyclicBarrier 要等固定数量的线程都到达了栅栏位置才能继续执行作用于线程                 CountDownLatch 只需等待数字倒数到 0作用于事件                 CountDownLatch 是在调用了 countDown 方法之后把数字倒数减 1而 CyclicBarrier 是在某线程开始等待后把计数减 1。         可重用性不同                 CountDownLatch不可重用锁打开后就不能重用了                 CyclicBarrier可重用满足线程数量后可自动重新计数也可调用reset方法进行重置CyclicBarrier。         执行动作不同                 CyclicBarrier 有执行动作 barrierAction而 CountDownLatch 没这个功能。 3、Java内存模型 3.1、Java内存模型JMM JVM内存模型和Java虚拟机的运行时区域有关。         程序计数器、Java堆、虚拟机栈、方法区、运行时常量池。         .java文件-编译.class文件-机器指令-CPU运行机器指令 Java内存模型JMM和Java的并发编程有关。         JMM 是一组规范保证同一个程序在不同虚拟机上运行可得到相同的结果。         实现java程序在各种不同的平台上都能达到内存访问的一致性。         重排序、原子性、内存可见性。 3.2、指令重排序 在保证业务逻辑不变的前提下对指令执行的顺序进行调整进而提高处理速度。 重排序的时机         编译器优化、CPU重排序、内存重排序 3.3、Java原子操作的注意事项 3.3.1、Java中的原子操作 除了 long 和 double 之外的基本类型int、byte、boolean、short、char、float的读/写操作都天然的具备原子性所有引用 reference 的读/写操作加了 volatile 后所有变量的读/写操作包含 long 和 double。这也就意味着 long 和 double 加了 volatile 关键字之后对它们的读写操作同样具备原子性volatile修饰的变量只能保证读/写的原子性不能保证组合操作的原子性。在 java.concurrent.Atomic 包中的一部分类的一部分方法是具备原子性的比如 AtomicInteger 的 incrementAndGet 方法。 3.3.2、long和double的原子性 long 和 double 的值需要占用 64 位的内存空间而对于 64 位值的写入可以分为两个 32 位的操作来进行。 而在目前各种平台下的主流虚拟机的实现中几乎都会把 64 位数据的读写操作作为原子操作来对待因此我们在编写代码时一般不需要为了避免读到“半个变量”而把 long 和 double 声明为 volatile 的。 3.4、内存可见性 工作内存保存的是主内存的副本。 线程变量更改后不能立即更新到主内存导致其他线程不能及时获取最新的数据。 3.5、主内存和工作内存的关系 所有的变量都存储在主内存中同时每个线程拥有自己独立的工作内存而工作内存中的变量的内容是主内存中该变量的拷贝线程不能直接读 / 写主内存中的变量但可以操作自己工作内存中的变量然后再同步到主内存中这样其他线程就可以看到本次修改主内存是由多个线程所共享的但线程间不共享各自的工作内存如果线程间需要通信则必须借助主内存中转来完成 3.6、happens-before原则 3.6.1、定义 如果第一个操作 happens-before 第二个操作那么我们就说第一个操作对于第二个操作一定是可见的也就是第二个操作在执行时就一定能保证看见第一个操作执行的结果。 如果有操作 x 和操作 y用 hb(x, y) 来表示 x happens-before y。 3.6.2、规则 锁操作的 happens-before 规则操作 A 是解锁而操作 B 是对同一个锁的加锁那么 hb(A, B) 。 线程 A 在解锁之前的所有操作对于线程 B 的对同一个锁的加锁之后的所有操作而言都是可见的。 volatile 的 happens-before 规则对一个 volatile 变量的写操作 happen-before 后面对该变量的读操作。 如果变量被 volatile 修饰那么每次修改之后其他线程在读取这个变量的时候一定能读取到该变量最新的值。 3.7、volatile作用 保证可见性 volatile修饰的变量直接写入到主内存中不存在主内存和工作内存同步造成的数据延迟。 禁止重排序 由于编译器或 CPU 的优化代码的实际执行顺序可能与我们编写的顺序是不同的这在单线程的情况下是没问题的但是一旦引入多线程这种乱序就可能会导致严重的线程安全问题。 3.8、单例模式的双重检查锁模式 3.8.1、实现代码 public class Singleton {private static volatile Singleton singleton;private Singleton() {}public static Singleton getInstance() {if (singleton  null) {synchronized (Singleton.class) {if (singleton  null) {singleton  new Singleton();}}}return singleton;} } 3.8.2、实体对象为什么要加volatile 不加volatile时可能发生指令重排序顺序如上图所示在第二步时对象就不为null了此时另一个线程进行第一个ifnull判断不为空返回对象但此时的对象还没有进行初始化在使用时就可能发生问题。 4、CAS原理 4.1、CAS是什么 Compare-And-Swap比较并交换是乐观锁的底层原理。避免使用互斥锁。 CAS 有三个操作数内存值 V、预期值 A、要修改的值 B。CAS 最核心的思路就是仅当预期值 A 和当前的内存值 V 相同时才将内存值修改为 B。 4.2、优点 当多个线程同时使用 CAS 更新同一个变量时只有其中一个线程能够操作成功而其他线程都会更新失败但更新失败的线程并不会被阻塞而是被告知这次由于竞争而导致的操作失败但还可以再次尝试原子性 CAS 相关的指令是具备原子性的这个组合操作在执行期间不会被打断这样就能保证并发安全。 4.3、CAS应用场景 并发容器ConcurrentHashMap、ConcurrentLinkedQueue数据库更新前检查版本号在更新数据时我们可以利用 version 字段在数据库中实现乐观锁和 CAS 操作而在获取和修改数据时都不需要加悲观锁 原子类Unsafe类 4.4、CAS导致的问题 ABA问题(可以通过添加版本号解决)假设有两个线程——线程1和线程2两个线程按照顺序进行以下操作 线程1读取内存中数据为A         线程2将该数据修改为B         线程2将该数据修改为A         线程1对数据进行CAS操作         第4步中的A已经不是第1步中的A值了。 比如栈顶问题-一个栈的栈顶经过两次(或多次)变化又恢复了原值但是栈可能已发生了变化 高竞争下的开销问题在并发冲突概率大的高竞争环境下CAS一直失败会一直重试导致CPU开销较大。 解决方法增加重试阈值 5、死锁问题 5.1、定义 死锁就是两个或多个线程或进程被无限期地阻塞相互等待对方手中资源的一种状态。 5.2、条件 互斥共享资源同一时间只能被一个线程使用。 请求与条件保持当一个线程因请求资源而阻塞时则需对已获得的资源保持不放。如果在请求资源时阻塞了并且会自动释放手中资源例如锁的话那别人自然就能拿到我刚才释放的资源也就不会形成死锁。 不剥夺条件线程已获得的资源在未使用完之前不会被强行剥夺 循环等待条件多个线程分别持有对方所需的资源并形成环路。         比如         线程1持有锁A尝试获取锁B         线程2持有锁B尝试获取锁C         线程3持有锁C尝试获取锁A。 5.3、命令行定位死锁(jstack) 查询当前Java程序的pid${JAVA_HOME}/bin/jps获取线程获取锁的信息${JAVA_HOME}/bin/jstack pid 5.4、如何解决死锁 5.4.1、线上死锁 立刻保存JVM信息、日志信息然后立刻重启服务。 5.4.2、避免死锁 顺序加锁锁嵌套时保证多个Lock以相同的顺序请求加锁超时放弃Lock接口的tryLock(long time, TimeUnit unit)按照固定时长等待锁获取锁超时后主动释放已经获得的锁尽量避免同一个线程对多个Lock进行锁定 5.4.3、检测与恢复策略(先允许系统发生死锁然后再解除) 终止线程线程优先级先终止优先级低的线程         占用资源先终止占用资源少的线程         运行时间先终止运行时间少的线程。 资源抢占剥夺某个线程已经获取的资源供其他线程使用。(线程回退、释放资源) 5.4.4、鸵鸟策略 死锁发生概率极小时允许死锁发生发生后再人工处理死锁比如重启服务等。 6、final关键字和不变性 6.1、用法 修饰变量该变量一旦被赋值就不能修改                 成员变量声明变量时直接赋值构造函数中赋值、类的构造代码块中赋值。                 静态变量声明变量时直接赋值静态代码块中赋值。                 局部变量在使用前进行赋值即可。 修饰入参                 在方法内部不能修改该参数 修饰对象时该对象的引用不可变该对象的内容是可变的。 修饰方法被final修饰的方法不能被重写即不能被override修饰类该类不能被继承 6.2、为什么String被设计成不可变的 节省大量内存空间使用字符串常量池两个字符串变量内容一致就会指向同一个对象而不需要创建新对象。 保证hash值的唯一性用作HashMap的key保证对同一个String进行hash能获得相同的hash值。 避免重复计算hash值String中有个hash成员变量用以缓存hashcode不用每次都计算hash值。 线程安全 7、AQS框架 是一个用于构建锁、同步器等线程协作工具类的框架。 应用ReentrantLock、ReentrantReadWriteLock、Semaphore(信号量-许可证)、CountDownLatch(闭锁) 7.1、原理 三大核心状态(status)、队列、期望协作工具类去实现的获取/释放等重要方法。 State变量可以理解成同步资源的锁状态值为0时表示当前资源未被线程占用值不为0时表示当前共享资源已被线程获取锁。 AQS就是基于CLH队列用volatile修饰共享变量state线程通过CAS去改变状态符成功则获取锁成功失败则进入等待队列等待被唤醒。 AQS是一个多线程访问同步资源的的同步器框架。该框架维护了一个volatile int state(共享资源)和一个FIFO(CLH双向队列)线程等待队列(多线程争夺共享资源时会进入此队列)。 AQS一般以继承的方式被使用重入锁ReentrantLock、闭锁、栅栏等都用到了AQS。 AQS的实现依赖内部的同步队列FIFO双向队列如果当前线程获取同步状态失败AQS会将当前线程以及等待状态等信息构造成一个Node将其加入同步队列的尾部同时阻塞当前线程当同步状态释放时唤醒队列的头节点。 状态(status)一个volatile int state(共享资源)。表示线程协作工具类的业务逻辑和状态。 信号量里表示许可证的数量 CountDownLatch里表示倒数的数量 ReentrantLock中表示锁的占有情况 CAS乐观锁实现通过compareAndSetState 及 setState两个方法修改status的值。 FIFO队列存储等待的线程。充当线程的“排队管理器”。         如果当前线程获取同步状态失败AQS会将该线程以及等待状态等信息构造成一个Node将其加入同步队列的尾部同时阻塞当前线程当同步状态释放时唤醒队列的头节点。 获取/释放方法获取方法                 ReentrantLock 中的 lock 方法status0获取成功                 Semaphore 中的 acquire 方法status正数获取成功                 CountDownLatch 获取方法就是 await 方法status0获取成功。         释放方法                 ReentrantLock的unLock方法                 Semaphore的release方法                 CountDownLatch 的countDown方法。 7.2、线程协同工具类(AQS实现) 实现类只需要实现共享资源state的获取和释放方式即可。 独占只有一个线程能执行-ReentrantLock 共享多个线程可以同时执行-Semaphore、CountDownLatch、CyclicBarrier 独占和共享ReentrantReadWriteLock 以上内容为个人学习理解如有问题欢迎在评论区指出。 部分内容截取自网络如有侵权联系作者删除。
http://www.w-s-a.com/news/133418/

相关文章:

  • 网站建设服务器可以租吗wordpress微信打赏
  • 网站制作的重要流程图大连网站优化快速排名
  • 河南省住房建设厅官方网站注册公司邮箱需要什么
  • 美橙网站注册华为手机网站建设策划方案论文
  • 河南省和建设厅网站首页在线图片翻译
  • 关于备案空壳网站清理通知去别人网站挂黑链
  • 做网站待遇世界购物平台排行榜
  • 售后服务网站什么网站免费做简历模板
  • 网站模板怎么修改成都网站优化seo
  • 给装修公司做推广的网站wordpress站点的根目录
  • 怎么创建企业网站wordpress怎么做404页面跳转
  • 福建省住房和建设厅网站网站做著作权
  • 编程代码网站网站搭建的注意事项
  • 音乐网站排名公司如何做自己的网站
  • 网站设计模式三网合一网站源代码
  • 珠海市品牌网站建设哪家好宛城区网站制作
  • 网站维护工程师代写文章兼职
  • 贵州城乡和建设厅网站企业网站备案名称窍门
  • .cc后缀网站湛江霞山
  • 青岛制作网站软件ui设计培训哪里好
  • 网站建设的构思环保公司宣传册设计样本
  • 如何做微网站网站和网店的区别
  • 免费下载建设银行官方网站下载天河区做网站
  • 中文网站建设开发北京网站建设公司升上去
  • 邯郸网站设计 贝壳下拉服务器绑定网站打不开
  • 重庆网站建设帝玖科技手机网站建设价钱是多少
  • 广西建设厅网站行业网学新媒体运营要多少钱
  • 石家庄个人建站网站策划门户网什么意思
  • 沈阳市浑南区城乡建设局网站wordpress 批量打印
  • 网站建设都需学哪些天津网站建设交易