多线程

多线程性能问题

核能气质少年 提交于 2020-04-21 08:23:30
如何优化性能: 如果重复计算量大的话,使用缓存来保存旧的结果,以便下次计算时使用; 减少阻塞,运行和阻塞会增加上下文切换。 因为锁是串行的这会引起大量的阻塞:所以我们在使用锁的时候要尽量的做到以下几点: 减少锁的持有时间(尽量使用synchronized或者显示锁将不必要同步的代码移除加锁的范围内,但不要把一个synchronized块分拆成多个块这会适得其反); 减少请求锁的操作; 使用协调机制取代独占所。 使用分离锁可以增加并发访问容器的量.这可以使容器并发的get等相同的操作: 分离锁的实现: 使用多个Object作为synchronized的代码块的"对象锁" 在取出或者写入的利用 获取对象的hash%锁数量 随即使用一个"对象锁" 分离锁:其实就是使用一个Array保存固定数量的Object(其实随便任意对象)使用这些对象的锁作为"分离锁".然后在get/put等操作中随即使用其中任意一个锁. 竞争锁是造成多线程应用程序性能瓶颈的主要原因: 区分竞争锁和非竞争锁对性能的影响非常重要。如果一个锁自始至终只被一个线程使用,那么 JVM 有能力优化它带来的绝大部分损耗。如果一个锁被多个线程使用过,但是在任意时刻,都只有一个线程尝试获取锁,那么它的开销要大一些。我们将以上两种锁称为非竞争锁。而对性能影响最严重的情况出现在多个线程同时尝试获取锁时。这种情况是 JVM 无法优化的

【Java并发性和多线程】线程安全与共享资源

岁酱吖の 提交于 2020-04-17 03:37:35
【推荐阅读】微服务还能火多久?>>> 本文为转载学习 原文链接: http://tutorials.jenkov.com/java-concurrency/thread-safety.html 译文链接: http://ifeve.com/thread-safety/ 允许被多个线程同时执行的代码称作线程安全的代码。线程安全的代码不包含竞态条件。当多个线程同时更新共享资源时会引发竞态条件。因此,了解Java线程执行时共享了什么资源很重要。 局部变量 局部变量存储在线程自己的栈中。也就是说,局部变量永远也不会被多个线程共享。所以,基础类型的局部变量是线程安全的。下面是基础类型的局部变量的一个例子: public void someMethod(){ long threadSafeInt = 0; threadSafeInt++; } 局部的对象引用 对象的局部引用和基础类型的局部变量不太一样。尽管引用本身没有被共享,但引用所指的对象并没有存储在线程的栈内。所有的对象都存在共享堆中。如果在某个方法中创建的对象不会逃逸出( 译者注:即该对象不会被其它方法获得,也不会被非局部变量引用到 )该方法,那么它就是线程安全的。实际上,哪怕将这个对象作为参数传给其它方法,只要别的线程获取不到这个对象,那它仍是线程安全的。下面是一个线程安全的局部引用样例: public void someMethod

【Java并发性和多线程】竞态条件与临界区

老子叫甜甜 提交于 2020-04-17 03:37:10
【推荐阅读】微服务还能火多久?>>> 本文为转载学习 原文链接: http://tutorials.jenkov.com/java-concurrency/race-conditions-and-critical-sections.html 译文链接: http://ifeve.com/race-conditions-and-critical-sections/ 在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源。如,同一内存区(变量,数组,或对象)、系统(数据库,web services等)或文件。实际上,这些问题只有在一或多个线程向这些资源做了写操作时才有可能发生,只要资源没有发生变化,多个线程读取相同的资源就是安全的。 多线程同时执行下面的代码可能会出错: public class Counter { protected long count = 0; public void add(long value){ this.count = this.count + value; } } 想象下线程A和B同时执行同一个Counter对象的add()方法,我们无法知道操作系统何时会在两个线程之间切换。JVM并不是将这段代码视为单条指令来执行的,而是按照下面的顺序: 从内存获取 this.count 的值放到寄存器 将寄存器中的值增加value

Java线程图文总结

二次信任 提交于 2020-04-15 09:52:56
【推荐阅读】微服务还能火多久?>>> 实现方式 简单介绍一下Java多线程实现方式,有以下三种: 1、继承Thread类 2、实现Runnable接口 3、使用ExecutorService、Callable、Future实现有返回结果的多线程 区别是前两种执行完之后不带返回值,最后一种带返回值,其中最常用为前两种。 线程的状态 java线程的整个生命周期有5个状态:新建,就绪,运行中,阻塞,结束。 5个状态之间的关系将结合下图理解: 上图为java线程生命周期期间的各种命运,下面介绍常见的几种命运。 命运一 : 新线程创建成功,调用start()进入就绪状态,即进入待运行的线程池中等待,等待获取CPU的使用权。当获得CPU使用权,该线程从就绪状态进入运行状态。运行过程中,运气好的,一次运行就把所要执行的任务执行完毕,线程结束;命运不好的,运行中途被CPU暂停运行,重新回到就绪状态,等待分配,然后再等待进入运行期,直到最后运行完毕,最后结束。 命运二 : 新线程创建成功,进入就绪状态,获取了CPU使用权,处于运行状态。这里意外出现,该线程执行了sleep、yield、join三者其中一个命令。sleep、join需要被暂停执行一段时间,线程进入阻塞状态。休息时间到,再重新进入就绪状态;而yield是从运行状态直接跳会就绪状态。当到了就绪状态后再重新等待CPU调度,重新进入运行期

关于java并发编程的一些概念及策略

谁都会走 提交于 2020-04-14 01:32:02
【今日推荐】:为什么一到面试就懵逼!>>> 最近抽出了点时间,把java并发编程的一些概念和策略总结了一下: 1. 同一个程序中的多个线程可以被同时调度到多个 CPU 上(利用这一点通常能提高 cpu 的使用率) 2. 多线程运用的例子: RMI 、 Servlet 、 GUI (通常情况下: GUI 对象都只能在实事件线程中访问且 GUI 的对象是被封闭在 单个线程当中)、 Timer 等 3. 只有当类中仅包含自己的状态时,线程安全类才是有意义的 4. 在一定条件下,可以安全地放宽状态变量的封装性 5. 同步术语: sychronized 、 volatile 类型的变量、显式锁、原子变量 (concurrent 包中) 6. 最常见的竞态条件:先检查后执行( check-and-act ),读取 -- 修改 -- 写入 7. 内置锁 : 可重入(可重复获取相同的锁) 8. 在构造方法中可以创建线程,但最好不要启动线程,以防止启动的线程访问未完全构造的 this 引用 9. 构造方法中调用非 private 和 final 方法 (即有可能被复写的方法) 时 ,也会导致 this 引用逸出 10. 线程封闭的三种方式: Ad-hoc 线程封闭、栈封闭、 ThreadLocal 类 11. final 域(引用不指向可变对象的情况下)是线程安全的 12. 安全发布对象的常用模式:

java5线程并发库的应用

筅森魡賤 提交于 2020-04-12 09:12:28
一、线程池 1、线程池的概念与Executors类的应用 > 创建固定大小的线程池 > 创建缓存线程池 > 创建单一线程池( 如何实现线程死掉后重启? ) 2、关闭线程池 > shutdown与shutdownNow的比较 前者是任务执行完毕即关闭程序,或者表示立即关闭而不会关心任务是否已经完成。 3、用线程池启动定时器 > 调用ScheduledExecutorService的schedule方法,返回的ScheduleFuture对象可以取消任务 > 支持间隔重复任务的定时方式,不直接支持绝对定时方式,需要转换成相对时间方式 二、代码描述 1、ThreadPoolTest.java 常见几种线程池类型 /** * @Title: ThreadPoolTest.java * @Package com.lh.threadtest.t8 * @Description: TODO * @author Liu * @date 2018年1月17日 下午2:17:40 * @version V1.0 */ package com.lh.threadtest.t8; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent

CyclicBarrier处理控制多线程顺序

生来就可爱ヽ(ⅴ<●) 提交于 2020-04-10 16:51:48
一直苦于无法控制多线程的处理顺序,最近看到java提供了很好的工具,所以抓过来学习下。但是看了一通注释还有网上的一堆解释,看的头晕。还是写一个测试代码来理解好了。 示例代码实现了,多个线程处理list加总和的问题。 主要有两点需要注意: 1,通过CyclicBarrier来控制多线程处理流程 2,通过synchronized来同步汇总总和 package com.thread; import java.util.ArrayList; import java.util.List; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * 模拟多个线程来处理list的数据加和,并最后打出结果 * @author owen.huang * */ class SumList implements Runnable{ private List<Integer> subList; private CyclicBarrier barrier; private Integer subSum = 0; public static Long allSum = 0l; private static Object obj = new Object();

java并发之同步辅助类CyclicBarrier

旧城冷巷雨未停 提交于 2020-04-10 16:51:27
CyclicBarrier 含义: 栅栏允许两个或者多个线程在某个集合点同步。当一个线程到达集合点时,它将调用await()方法等待其它的线程。线程调用await()方法后,CyclicBarrier将阻塞这个线程并将它置入休眠状态等待其它线程的到来。等最后一个线程调用await()方法时,CyclicBarrier将唤醒所有等待的线程然后这些线程将继续执行。CyclicBarrier可以传入另一个Runnable对象作为初始化参数。当所有的线程都到达集合点后,CyclicBarrier类将Runnable对象作为线程执行。 方法 : await():使线程置入休眠直到最后一个线程的到来之后唤醒所有休眠的线程 例子 在矩阵(二维数组)中查找一个指定的数字。矩阵将被分为多个子集,每个子集交给一个线程去查找。当所有线程查找完毕后交给最后的线程汇总结果。 查找类:在一个子集中查找指定数字,找到之后把结果存储后调用await()方法置入休眠等待最后一个线程的到来唤醒 import java.util.List; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class Searcher implements Runnable {

面试问我,创建多少个线程合适?我该怎么说

*爱你&永不变心* 提交于 2020-04-08 08:54:43
| 如果好看,请给个赞 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough 现陆续将Demo代码和技术文章整理在一起 Github实践精选 ,方便大家阅读查看,本文同样收录在此,觉得不错,还请Star 为什么要使用多线程? 防止并发编程出错最好的办法就是不写并发程序 既然多线程编程容易出错,为什么它还经久不衰呢? A:那还用说,肯定在某些方面有特长呗,比如你知道的【它很快,非常快】 我也很赞同这个答案,但说的不够具体 并发编程适用于什么场景? 如果问你选择多线程的原因就是一个【快】字,面试也就不会出那么多幺蛾子了。你有没有问过你自己 并发编程在所有场景下都是快的吗? 知道它很快,何为快?怎样度量? 想知道这两个问题的答案,我们需要一个从【定性】到【定量】的分析过程 使用多线程就是在正确的场景下通过设置正确个数的线程来最大化程序的运行速度(我感觉你还是啥也没说) 将这句话翻译到硬件级别就是要充分的利用 CPU 和 I/O 的利用率 两个正确得到保证,也就能达到最大化利用 CPU 和 I/O的目的了。最关键是,如何做到两个【正确】? 在聊具体场景的时候,我们必须要拿出我们的专业性来。送你两个名词 buff 加成 CPU 密集型程序 I/O

面试问我,创建多少个线程合适?我该怎么说

故事扮演 提交于 2020-04-08 08:30:46
| 如果好看,请给个赞 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough 现陆续将Demo代码和技术文章整理在一起 Github实践精选 ,方便大家阅读查看,本文同样收录在此,觉得不错,还请Star 为什么要使用多线程? 防止并发编程出错最好的办法就是不写并发程序 既然多线程编程容易出错,为什么它还经久不衰呢? A:那还用说,肯定在某些方面有特长呗,比如你知道的【它很快,非常快】 我也很赞同这个答案,但说的不够具体 并发编程适用于什么场景? 如果问你选择多线程的原因就是一个【快】字,面试也就不会出那么多幺蛾子了。你有没有问过你自己 并发编程在所有场景下都是快的吗? 知道它很快,何为快?怎样度量? 想知道这两个问题的答案,我们需要一个从【定性】到【定量】的分析过程 使用多线程就是在正确的场景下通过设置正确个数的线程来最大化程序的运行速度(我感觉你还是啥也没说) 将这句话翻译到硬件级别就是要充分的利用 CPU 和 I/O 的利用率 两个正确得到保证,也就能达到最大化利用 CPU 和 I/O的目的了。最关键是,如何做到两个【正确】? 在聊具体场景的时候,我们必须要拿出我们的专业性来。送你两个名词 buff 加成 CPU 密集型程序 I/O