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

个人公益网站怎么制作wordpress固定链接无法访问

个人公益网站怎么制作,wordpress固定链接无法访问,网站开发 功能不会写,手机怎么自己做网站文章目录 1. Java8新特性1.1 Lambda表达式1.2 函数式接口1.3 Stream流式计算#xff0c;应用了上述函数式接口能力1.4 接口增强 2. 常用原子类3. 多线程与高并发-juc3.1 谈一谈对volatile的理解3.2 谈一谈对JMM的理解3.3 谈一谈对CAS及底层原理的理解3.4 谈一谈对ABA问题及原子… 文章目录 1. Java8新特性1.1 Lambda表达式1.2 函数式接口1.3 Stream流式计算应用了上述函数式接口能力1.4 接口增强 2. 常用原子类3. 多线程与高并发-juc3.1 谈一谈对volatile的理解3.2 谈一谈对JMM的理解3.3 谈一谈对CAS及底层原理的理解3.4 谈一谈对ABA问题及原子更新引用的理解3.5 谈一谈集合不安全的情况3.6 谈一谈Java常用锁3.7 谈一谈常见的线程计数器3.8 谈一谈阻塞队列3.9 谈一谈线程池以及ThreadPoolExecutor3.10 谈一谈死锁以及定位分析3.11 谈一谈强引用、软引用、弱引用和虚引用3.12 谈一谈六种常见的OOM 4. JVM核心知识点4.1 JVM垃圾回收如何确定垃圾及GC Roots4.2 常用的JVM基本配置参数4.3 垃圾收集算法与垃圾回收器4.4 Linux系统变慢如何定位4.5 Github骚操作 1. Java8新特性 1.1 Lambda表达式 java8引入了一个新的操作符-该操作符将表达式拆分为两部分左侧Lambada表示表达式的参数列表右侧Lambda表示所需要执行的功能规则(左侧)-(右侧)new Thread( ()- System.out.println(abc)).start();1.2 函数式接口 package com.gwolf; FunctionalInterface public interface MyPredicateT {public boolean test(T t); }1.3 Stream流式计算应用了上述函数式接口能力 StreamAPI是java8中处理集合的关键抽象概念它可以指定您希望对集合进行的操作 可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作就类似于使用SQL执行的数据库查询。1.4 接口增强 Java8允许我们给接口添加一个非抽象的方法实现只需要使用 default关键字即可这个特征又叫做扩展方法示例如下2. 常用原子类 引入原子操作类的原因 在多线程环境下对于Java中的运算操作例如自增或自减例如num解析为numnum1显然这个操作不具备原子性多线程并发共享这个变量时必然会出现问题线程不安全。因此需要引入各种原子操作类。AtomicInteger提供线程安全的原子操作方式来进行相关运算(包括加减)因此原子操作类十分适合多线程、高并发情况下的使用。 1AtomicBoolean: 原子更新布尔类型 2AtomicInteger: 原子更新整型 3AtomicLong: 原子更新长整型以上3个类提供的方法几乎一模一样以AtomicInteger为例进行详解AtomicIngeter的常用方法如下 AtomicInteger构造方法 1、public AtomicInteger(int initialValue) 创建具有给定初始值的新 AtomicInteger 2、public AtomicInteger() 创建具有初始值0的新 AtomicInteger AtomicInteger常用API 1、public final int get() 获取当前值 2、public final void set(int newValue) 设置为给定值 3、public final boolean compareAndSet(int expect, int update) CAS参数expect - 预期值 update - 新值 如果当前值 预期值则以原子方式将该值设置为给定的更新值返回 true如果当前值 ! 预期值返回 false,说明实际值与预期值不相等 4、public final int getAndIncrement() 以原子方式将当前值加 1。 5、public final int getAndDecrement() 以原子方式将当前值减 1。 6、public final int incrementAndGet() 以原子方式将当前值加 1。 7、public final int decrementAndGet() 以原子方式将当前值减 1。 8、public final int getAndAdd(int delta) 以原子方式将给定值与当前值相加。 9、public final int addAndGet(int delta) 以原子方式将给定值与当前值相加。3. 多线程与高并发-juc 主要包括volatile、jmm 、可见性、原子性、有序性 、AtomicInteger、 CAS 、ABA问题、Unsafe类、自旋锁 、 ABA问题、原子引用更新、如何规避ABA问题 3.1 谈一谈对volatile的理解 A、volatile是Java虚拟机提供的轻量级的线程同步机制轻量级的synchronized 特性 1、保证可见性 testvolatile01.java 2、保证有序性(禁止指令重排列) testvolatile03.java 3、不保证原子性 testvolatile02.javas 可见性某一线程中的变量发生变化其他线程可立刻得到通知拿到该变量的最新值 原子性也叫做完整性不可分割即某个线程在做某个具体操作时要么不执行要么彻底执行中间不可以加塞或者被分割。 有序性(禁止指令重排列)有序性只针对多线程计算机在执行程序时为了提高性能编译器和处理器常常会对指令做重排列一般分为三种 ​ 单线程环境可以确保程序最终执行结果和代码顺序执行的结果一致但在多线程环境中多个线程交替执行由于编译器优化重排列的结果两个线程使用的变量能否保证一致性是无法确定的。类似于做题先做简单题后做难题。多线程环境下程序执行也不是按顺序执行的但满足happens before原则指令之间的数据依赖性 ​ 在多线程环境下指令重排会导致变量值不一致必须禁止指令重排列volatile修饰的变量就可以禁止指令重排。 B、volatile为什么不能保证原子性 一个被volatile修饰的变量那么肯定可以保证每次读取这个变量值的时候得到的值是最新的但是一旦需要对变量进行n这样的非原子操作如果多个线程操作n就会出现写值丢失的情况线程不安全也就不会保证这个变量的原子性了。 C、既然volatile不保证原子性如何解决 1、synchronized方法进行加锁效率低 2、使用原子包装类Atomic保证线程安全。 例如AtomicInteger nnew AtomicInteger(),默认为0 通过其方法atomic_i.getAndIncrement(); // 原子操作1 实现原子操作 D、你在哪些地方使用过volatile? 1、单例模式并发多线程环境下懒汉单例模式按道理应该实例化一次实际却实例化很多次而且不确定次数【8种单例模式】 如何解决 ​ a、方法1 synchronized: public synchronized static testSingletonDemo getInstance() ​ b、方法2DCLDouble Check Lock 双端检锁机制 volatile关键字 2、CAS 示例 饿汉单例模式: 类加载时就完成了初始化所以类加载较慢但获取对象的速度快(线程安全) 懒汉单例模式线程不安全 懒汉单例模式优化-001线程安全加锁synchronized 懒汉单例模式优化-002线程安全volatile双端检锁机制 3.2 谈一谈对JMM的理解 JMMJava内存模型本身是一种抽象的概念并不真实存在它描述的是一组规范或规则通过这组规范定义了程序中各个遍历的访问方式。 JMM特性可见性、原子性、禁止指令重排列保证有序性 JMM关于线程同步的规定 ​ 1、线程加锁前必须读取主内存中共享变量的最新值读到自己的工作内存 ​ 2、线程解锁前必须把共享变量的值刷新到主内存。 ​ 3、加锁、解锁是同一把锁。 ​ 由于JVM运行程序的实体是线程而每个线程创建时JVM会为其分配一个工作内存也叫做栈空间工作内存是每一个线程的私有数据区域而Java内存模型中规定所有变量都存储在主内存主内存是共享区域所有线程都可以访问。但线程对变量的读写操作必须在自己的工作内存中进行因此 ​ 1、首先线程要将变量从主内存拷贝到自己的工作内存 ​ 2、然后线程在自己的工作内存对变量进行操作 ​ 3、操作完成后再将变量的值写回主内存 ​ 各个线程的工作内存存储的是主内存的变量副本拷贝不能直接操作主内存的变量。因此不同线程无法访问对方的的工作内存线程间的通信必须通过主内存来完成过程如下 JMM线程安全性如何得到保证 1、工作内存与主内存同步延迟导致的可见性问题可以通过synchronized或volatile关键字解决可以使一个线程修改后的变量立即对其他线程可见。 2、对于指令重排导致的有序性问题可以通过volatile关键字解决它可以禁止指令重排优化。 3.3 谈一谈对CAS及底层原理的理解 CAS是Compare-And-Swap它是一条CPU并发原语它的功能是判断内存某个变量的值是否为期望值如果是则返回true并更改为新值如果不是则返回false这个过程是原子操作过程。 典型应用是原子操作类AtomicInteger的compareAndSet方法 compareAndSet(int expect, int update) 如果主内存真实值 线程期望值则以原子方式将该值设置为给定的更新值返回 true 如果主内存真实值 ! 线程期望值返回 false,说明实际值与预期值不相等 再次强调CAS是一种系统原语由若干条指令组成原语的执行必须是连续的在执行过程中不可以中断也就是说CAS是一条CPU的原子指令不存在数据不一致的情况也就是线程安全。 CAS底层原理Unsafe类与自旋锁 Unsafe是CAS核心类由于Java无法直接访问底层操作系统需要调用native本地方法来访问Unsafe相当于一个后门基于Unsafe类可以直接像C语言指针一样操作特定内存中的数据并直接调用底层资源执行相应任务。Unsafe类中的所有方法都是native修饰Java中CAS操作的执行都依赖于Unsafe中的方法。 // 举例getAndIncrement底层实现 getAndIncrement底层实现底层getAndAddInt()采用CAS思想 this: new* 出来的对象 VALUE 内存地址内存偏移量 1: 变动的数量执行过程假设线程A和线程B并发执行getAndAddInt操作 1、AtomicInteger里面的value值原始值为3根据JMM线程A、B各自持有一份值为3的变量副本在其工作内存。 2、线程A通过getIntVolatile得到value的值为3此时线程A被挂起。 3、线程B也通过getIntVolatile得到value的值为3并立即执行compareAndSetInt比较内存的值也为3成功修改value4结束收工。 4、此时线程A恢复执行compareAndSetInt发现自己工作内存的value值为3与主内存的4不一致修改失败只能重新读取主内存的value值。 5、线程A重新获取value值因为value被volatile修饰根据可见性原理它可以立即知道vlaue最新值然后执行compareAndSetInt进行比较替换知道成功。 总结因为每个线程执行过程中多了一步将本线程的变量值与主内存变量值比较的过程所以保证了线程安全。 CAS缺点1、由于通过循环do..while来实现没有加锁如果CAS长时间不成功会给CPU带来很大的开销2、只能保证一个共享变量的原子操作3、引发ABA问题AtomicInteger为什么使用CAS不使用synchronized 1、synchronized是对方法加锁同一时间段只能有一个线程访问数据一致性得到保证但是并发性下降 2、CAS使用do while语句没有加锁反复将期望值与真实值对比即保证了数据一致性也提高了并发性 3.4 谈一谈对ABA问题及原子更新引用的理解 ABA问题俗称狸猫换太子也即是说CAS算法实现的一个重要前提是需要取出主内存某时刻的数据并在当下时刻比较并替换那么在这个时间差内出现数据的变化比如下面这种情况尽管线程Thread01操作成功但是并不代表这个过程没有问题。 那如何解决ABA问题 ​ 带时间戳的原子引用AtomicStampedReference // todo 原子引用 3.5 谈一谈集合不安全的情况 HashMap put(K, V) // 将键/值映射存放到Map集合中key不允许重复否则会覆盖已有的key对应的值key、value允许为null remove(key) //删除Map集合中键为key的数据并返回其所对应value值。 get(key) //返回指定键所映射的值没有该key对应的值则返回null isEmpty () //判断Map集合中是否有数据如果没有则返回true否则返回false containsKey(Object key) //判断集合中是否包含指定键 containsValue(Object value) //判断集合中是否包含指定值 size() //返回Map集合中数据数量1.底层数据结构 ​ jdk7数组链表数组初始长度16扩容数组大小增加为原来的2倍 ​ jdk8数组链表红黑树数组初始长度16当链表长度大于8会将链表转为红黑树 2.实现原理 JAVA7数组链表 大方向上HashMap 底层是一个数组然后数组中每个元素是一个单向链表 put(key, value)执行过程 1、根据输入的key计算key的哈希值Hash(key)并得到对应数组下标Hash(key)%N。 2、当计算得到的下标出现一致时即哈希冲突此时需要存储到上一个entry链表的下一个节点HashMap通过链址法解决哈希冲突。 get(key) 执行过程 1、首先根据key得到一个数组下标Hash(key)%N 2、然后比较该下标hash值与hashkey值是否一致若key值也一致则返回对应的valuekey、hash(key)都一致 JAVA8数组链表红黑树 根据 Java7 的介绍根据 hash 值我们能够快速定位到数组的具体下标但是之后的话需要顺着链表一个个比较下去才能找到我们需要的时间复杂度取决于链表的长度为 O(n)。 为了解决链表过长查询效率过低的问题在 Java8 中当链表中的元素超过了 8 个以后会将链表转换为红黑树降低时间复杂度为 O(logN)。 put(key, value)执行过程 1、根据输入的key计算key的哈希值Hash(key)并得到对应数组下标Hash(key)%N。 2、当计算得到的下标出现一致时即哈希冲突此时需要存储到上一个entry链表的下一个节点HashMap通过链址法解决哈希冲突。 ​ 3、当链表长度大于8时将链表改为红黑树 // java8默认类成员变量值static final int DEFAULT_INITIAL_CAPACITY 1 4; // 默认初始容量16必须是2的倍数也就是数组初始化容量为16static final int MAXIMUM_CAPACITY 1 30; // 最大容量 1073741824 2^30static final float DEFAULT_LOAD_FACTOR 0.75F; // 默认扩充因子static final int TREEIFY_THRESHOLD 8; // 当链表长度大于此值时将链表转成红黑树static final int UNTREEIFY_THRESHOLD 6; // 当红黑树元素小于此值时将红黑树转换成链表static final int MIN_TREEIFY_CAPACITY 64; // 当链表长度大于此值且容量大于64时才允许树形化链表即将链表转换成红黑树int threshold; // thresholdcapacity*loadFactor扩容阈值 表示当HashMap的size大于threshold时会执行resize(扩容)操作 final float loadFactor;// 装载因子size/capacity是用来衡量 HashMap 满的程度而不是占用桶的数量去除以capacityPS: 二叉搜索树-平衡二叉树-红黑树 口诀黑根黑叶红不邻【2-3-4】同祖等高只数黑【5】 为什么ArrayList是线程不安全的 ArrayList的底层实现 1、用了一个Object[]的数组用来保存所有的元素 2、用了一个size变量用来保存当前数组中已经添加了多少元素。add方法线程不安全 add方法添加一个元素的时候它可能会有两步来完成 1. 在elementData[size]的位置存放此元素 2. 集合个数加1:size1在单线程运行的情况下如果size0添加一个元素后此元素在位置elementData[0]而且size1,没有问题 但在多线程情况下比如有两个线程1. 线程A先将元素存放在位置0但还没有执行size1操作随后线程A暂停线程B得到运行机会。【elementData[0]Asize0】2. 线程B也添加元素因为此时size0所以线程B也将元素存放在位置0并执行size1操作。【elementData[0]Bsize1】3. 线程A继续运行执行size1操作【此时elementData[0]Bsize2】此时集合元素实际上只有一个存放在位置0而 size2。这就是“线程不安全”了。为什么HashMap是线程不安全的 Java7 HashMap线程不安全体现在由于多线程对HashMap进行扩容调用了HashMap#transfer(),导致线程死循环、数据丢失具体原因某个线程执行过程中被挂起其他线程已经完成数据迁移等CPU资源释放后被挂起的线程重新执行之前的逻辑数据已经被改变造成死循环、数据丢失。Java8 HashMap线程不安全体现在由于多线程对HashMap进行put操作调用了HashMap#putVal()导致数据覆盖1. 假设线程A、B都在进行put操作并且hash函数计算出的插入下标是相同的2. 当线程A执行完第六行代码后由于时间片耗尽导致被挂起而线程B得到时间片后在该下标处插入了元素完成了正常的插入3. 然后线程A获得时间片由于之前已经进行了hash碰撞的判断所有此时不会再进行判断而是直接进行插入这就导致了线程B插入的数据被线程A覆盖了从而线程不安全。1、故障现象java.util.ConcurrentModificationException2、导致原因并发线程争抢资源出现数据不一致导致写值丢失的现象。类似于花名册签字案例3、解决方案解决方案一: 使用各自线程安全的集合ListObject alnew Vector(); // ArrayList - Vector(synchronized)MapString,Stringmapnew ConcurrentHashMap(); // HashMap - ConcurrentHashMap、HashTablePS一般不采用HashTable其效率低下需要线程安全就使用concurrentHashMap不需要线程安全就使用HashMap解决方案二:Collections的静态方法,同步线程Collections.synchronizedList(al);Collections.synchronizedMap(mp);Collections.synchronizedSet(st);解决方案三: CopyOnWrite容器没有CopyOnWriteMapListObject alnew CopyOnWriteArrayList()SetObject setnew CopyOnWriteArraySet();CopyOnWriteArrayList原理写时复制、读写分离、lock CopyOnWrite容器是一个写时复制的容器往容器内添加元素的时候不直接在容器内添加而是1、先将当前容器Object[]进行复制copy复制得到一个新的容器Object[] newElements2、然后向新容器添加元素并将原容器的引用指向当前容器。好处:可以对CopyOnWrite并发的读而不需要加锁。因为当前容器不会添加任何元素3、其他线程使用新的容器newElements。所有CopyOnWrite是一种读写分离的思想读和写不同的容器。3.6 谈一谈Java常用锁 主要包括公平锁/非公平锁/可重入锁(递归锁)/自旋锁/独占锁(写锁)/共享锁(读锁)/读写锁 1. 公平锁 在多线程环境下按照线程申请锁的顺序来获取锁性能不高类似排队打饭先来后到 2. 非公平锁 指线程获取锁的顺序不是按照申请锁的顺序有可能后申请的线程比先申请的线程优先获得锁。线程执行效率提高吞吐量大但是在高并发的环境下有可能会造成优先级反转或饥饿现象。 3. 可重入锁 又称为递归锁指同一线程外层函数获得锁之后内层递归函数仍然能获取锁的代码即同一线程在外层方法获取锁后进入内层方法自动获取锁可以防止死锁 4. 自旋锁 指尝试获取锁的线程不会阻塞而是采用循环的方式尝试获取锁这样可以减少线程上下文切换的消耗缺点是循环会消耗CPU资源。典型Unsafe.getAndAddInt() 5. 读写锁读时共享、写时独占可重入读写锁ReentrantReadWriteLock基本上可以取代synchronizedprivate ReentrantReadWriteLock rwlocknew ReentrantReadWriteLock();rwlock.writeLock().lock(); //加写锁rwlock.readLock().lock(); //加读锁锁升级1. 锁的状态总共有四种:无锁状态、偏向锁、轻量级锁和重量级锁。2. 随着锁的竞争锁可以从偏向锁升级到轻量级锁再升级为重量级锁(但是锁的升级是单向的也就是说只能从低到高升级不会出现锁的降级。3.7 谈一谈常见的线程计数器 a、CountDownLatch让一些线程阻塞直到另一些线程完成一系列操作才被唤醒,初始值为target计数器0再执行做减法以前我们都是第七个线程睡眠一段时间确保前六个线程执行完CountDownLatch countDownLatch new CountDownLatch(6); countDownLatch.countDown();//计数器减1countDownLatch.await();//调用线程会被阻塞当计数器为0时才会被唤醒b、CyclicBarrier:字面意思是可循环使用的屏障让一组线程到达一个屏障时被阻塞直到最后一个线程到达屏障时屏障才会开门。初始值0计数器target再执行做加法CyclicBarrier cnew CyclicBarrier(7,()-{System.out.println(最后执行操作召唤神龙);}); c.await();//先来的线程被阻塞c、Semaphore信号量机制多个线程争抢多个共享资源。主要用于两个目的一是用于多个共享资源的互斥使用另一个是用于控制并发线程数目争车位Semaphore snew Semaphore(3);//共享资源是3个停车位s.acquire();//占到车位s.release();//释放资源3.8 谈一谈阻塞队列 阻塞队列首先是一个队列当阻塞队列为空时从队列中获取元素的操作会被阻塞当阻塞队列为满时往队列里添加元素的操作将会被阻塞。 阻塞队列的优点我们不需要决定什么时候去阻塞线程什么时候去唤醒线程不需要考虑wait、notify因为这一切阻塞队列BlockingQueue一手包办了。在并发concurrent包发布之前在多线程环境下程序员需要控制这些线程同步的细节并且兼顾系统的效率和安全性。 如何高效管理阻塞队列ArrayBlockingQueue: 由数组结构组成的有界阻塞队列LinkedBlockingQueue: 由链表结构组成的有界阻塞队列(但大小默认为Integre.MAX_VALUE)也可以认为是无界阻塞队列谨慎使用SynchronousQueue: 不存储元素的阻塞队列也即单个元素的队列有且仅有1个元素PriorityBlockingQueue: 支持优先级排序的阻塞队列DelayQueue: 使用优先级队列实现的延迟无界阻塞队列LinkedTransferQueue: 由链表结构组成的无界阻塞队列LinkedBlockingDeque: 由链表结构组成的无向阻塞队列核心方法 方法类型抛出异常特殊值阻塞超时增加add(e)offer(e)put(e)offer(e,time,unit)删除remove()poll()take()poll(time ,unit)查询element()peek()NONO 抛出异常当阻塞队列满时再添加元素add(e)会抛出异常:lleagalStateException:Queue Full当阻塞队列空时在删除元素remove()、remove(e) 会抛出异常:NoSuchElementException特殊值插入方法offer(), 成功为true失败为false删除方法poll(), 成功为队内元素失败为null阻塞当阻塞队列满时生产者再继续往队列添加元素put(e)队列会一直阻塞直到成功或者响应中断推出。当阻塞队列空时消费者线程试图从队列take元素队列会一直阻塞消费者进程直到队列可用。超时建议使用阻塞队列用在哪里1、生产者消费者模式传统版、阻塞队列版待定2、线程池3、消息中间件 3.9 谈一谈线程池以及ThreadPoolExecutor 线程池就是容纳多个线程的容器其中的线程可以反复使用省去了频繁创建线程对象、销毁线程的操作避免系统资源的浪费。 线程池的优势线程复用 通过线程复用降低线程的创建和销毁造成的消耗提升响应速度 当任务到达时任务可以不需要等到线程创建就可以执行。提高线程的可管理性 控制线程的并发数量统一分配、管理线程常用的线程池 1、Executors.newCachedThreadPool(int) 执行短期异步的小程序SynchronousQueue 2、Executors.newFixedThreadPool(int) 执行长期的任务 LinkedBlockingQueue 3、Executors.newSingleThreadExecutor(int) 任务按序执行 LinkedBlockingQueue 4、Executors.newScheduledThreadPool(int) 延迟重复执行线程synchronized保证三大性原子性有序性可见性 volatile保证有序性可见性不能保证原子性常用线程池底层实现 自定义线程池ThreadPoolExecutor 1:核心线程数(corePoolSize) 线程池中常驻核心线程数 2:最大线程数(maximumPoolSize) 线程池能够容纳同时执行的最大线程数 3:keepAliveTime: 非核心线程最大存活时间若当前线程池数量超过核心线程数corePoolSize当空闲时间达到keepAliveTime多余非核心线程会被销毁直到只剩下corePoolSize个线程。 4:unit: keepAliveTime的单位 5:任务队列(workQueue) 被提交但尚未执行的任务存放在阻塞队列中 6:线程工厂(threadFactory): 用于创建线程一般默认即可。 7:拒绝策略(handler) 表示当等待队列满了并且工作线程大于等于线程池的最大线程数常见拒绝策略AbortPolicy(默认) 直接抛出异常RejectedExecutionException阻止系统正常运行CallerRunsPolicy 调用者优先策略该策略不会抛弃任务也不会抛出异常而是将某些任务回退DiscardOldestPolicy 抛弃队列中等待最久的任务然后把当前任务加入队列中尝试再次提交当前任务DiscardPolicy 直接丢弃任务不做任何处理也不抛出异常。如果允许任务丢失可以使用底层原理 1、在创建了线程池之后等待提交过来的任务请求 2、当调用execute()方法后添加一个请求任务2.1 如果正在运行的线程数量小于corePoolSize则立即执行该任务2.2 如果正在运行的线程数量大于等于corePoolSize则将该任务放进队列 workQueue2.3 如果任务队列满了并且正在运行的线程数量小于maximumPoolSize那么线程池创建非核心线程执行任务2.4 如果任务队列满了并且正在运行的线程数量大于等于maximumPoolSize那么线程池启动拒绝策略执行。3、当一个线程完成任务时它会从队列取下一个任务执行 4、当一个线程无事可做超过一定的时间keepAliveTime线程池会判断4.1 如果运行的线程数大于corePoolSize那么会停掉该非核心线程4.2 最后线程池的线程数目收缩到corePoolSize的大小3.10 谈一谈死锁以及定位分析 死锁指的是两个或两个以上进程在执行过程中因争夺资源而造成的互相等待的现象若无外力干涉那他们将无法继续推进下去如果系统资源充足进程的资源请求都能得到满足死锁出现的可能性较低否则会因争夺有限的资源而陷入死锁。系统资源不足、进程推进顺序不合适、资源分配不当 故障分析 1、打开IDEA控制台 2、定位Java线程:jps -l 3、查看异常进程号jstack 531 常用命令行 1、jps 查看本机后台java进程信息。 jps -l 2、jinfo 查看正在运行Java程序相关信息jinfo -flag 配置项 进程号jinfo -flags 进程号 3、jstack 打印线程的栈信息制作线程dump文件发现死锁 4、jmap 打印内存映射制作堆dump文件 5、jstat 性能监控工具 6、jhat 内存分析工具 7、jconsole 简易的可视化控制台 8、jvisualvm 功能强大的控制台 问题一synchronized和volatile区别1、synchronized可以修饰方法代码块而volatile只能用于修饰变量。2、sychronized可以保证线程的原子性、可见性、有序性而volatile能保证变量在多个线程之间的可见性、有序性但不能保证原子性。3、多线程访问sychronized会出现阻塞而访问volatile不会发生阻塞。4、volatile是线程同步的轻量级实现所以volatile性能比synchronized要好但是sychronized关键字在执行效率上逐渐得到提升在开发中使用synchronized关键字的比率还是比较大。问题二synchronized和lock区别1、synchronized是Java中的关键字是内置的语言实现而Lock是一个接口2、synchronized在发生异常时会自动释放线程占有的锁因此不会发生死锁而Lock在发生异常时如果没有主动通过unLock()去释放锁则很可能造成死锁现象因此需要在finally块中释放锁3、通过Lock可以知道有没有成功获取锁而synchronized却无法办到。4、Lock可以提高多个线程进行读操作的效率读写锁。在性能上来说如果竞争资源不激烈两者的性能是差不多的而当竞争资源非常激烈时即有大量线程同时竞争此时Lock的性能要远远优于synchronized。所以说在具体使用时要根据适当情况选择。3.11 谈一谈强引用、软引用、弱引用和虚引用 强引用默认支持模式当内存不足时JVM会进行垃圾回收对于强引用的对象就算是出现了OOM也不会对该对象进行回收。只要有一个强引用指向一个对象就说明对象还活着垃圾回收器不会回收这类对象。因此强引用是造成Java内存泄露的主要原因之一。【JVM永不回收】 软引用是一种相对强引用弱化了一些的引用需要用java.lang.SoftReference类来实现当系统内存充足时该对象不会被回收当系统内存不足时该对象会被垃圾收集器回收。软引用通常应用在对内存敏感的程序中比如高速缓存。【JVM内存够用的时候就保留不够用就回收】 弱引用弱引用需要用java.lang.weakReference类来实现对于只有弱引用的对象来说只要垃圾回收机制一运行不管JVM的内存空间是否足够都会立即回收该对象占有的内存。【JVM立即回收】 虚引用虚引用需要java.lang.ref.PhantomReference类来实现就是形同虚设虚引用不会决定对象的生命周期**在任何时候都会被垃圾回收器回收**并且不能单独使用必须要和引用队列ReferenceQueue联合使用。换句话说虚引用的唯一作用就是在这个对象被垃圾收集器回收的时候收到一个系统通知或者后续添加进一步的处理。 软引用应用场景 假如有一个应用需要读取大量的本地图片:如果每次读取图片都从硬盘读取则会严重影响性能如果一次性全部加载到内存中又可能造成内存溢出。此时使用软引用可以解决这个问题。设计思路:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系在内存不足时JVM会自动回收这些缓存图片对象所占用的空间从而有效地避免了OOM的问题。MapString, SoftReferenceBitmap imageCache new HashMapString, SoftReferenceBitmap();3.12 谈一谈六种常见的OOM java.lang.StackOverFlowError 栈溢出方法递归 java.lang.OutOfMemoryError:Java heap space 堆溢出new大对象 java.lang.OutOfMemoryError:Metaspace 元空间异常, 存储类信息、常量池、静态类 java.lang.OutOfMemoryError:Direct buffer memory 直接内存溢出本地内存溢出主要由NIO引起ByteBuffer.allocate(capacity); // 分配JVM堆内存属于GC管辖范围由于需要拷贝速度较慢ByteBuffer.allocateDirect(capacity); // 分配本地内存不属于GC管辖范围若本地内存用光那程序崩溃抛出该异常java.lang.OutofMemoryError:GC overhead limit exceeded GC回收时间过长超过98%时间进行垃圾回收GC并且回收不到2%的堆内存 java.lang.OutOfMemoryError:unable to create native thread 无法创建新的native线程准确来讲该异常与对应的平台有关 导致原因1、你的应用创建的太多的线程超过系统承载极限2、你的服务器并不允许创建那么多的线程如Linux默认单个进程只可以创建1024个线程 解决方法1、降低线程的数量2、扩大Linux默认线程设置的限制4. JVM核心知识点 4.1 JVM垃圾回收如何确定垃圾及GC Roots 垃圾内存中已经不再被使用的对象被成为垃圾 如何判断一个对象是否可以被回收 **引用计数法**简单来说给对象中添加一个引用计数器每当有一个地方引用它计数器加一每当有一个引用失效计数器减一任何时刻对象的计数器的值为0那么这个对象就是可回收对象。一般该方法已被舍弃主要原因在于很难解决对象之间互相循环引用的问题。 根搜索路径枚举根节点做可达性分析为了解决引用计数法的循环引用问题Java使用通过GC Roots做可达性分析的根搜索路径方法。通过一系列名为“GC roots”的对象作为起点从GC Roots的对象开始向下搜索如果一个对象到GC Roots没有任何引用链相连时则说明该对象可回收。 GC Roots的对象1、虚拟机栈中引用的对象 局部变量表2、方法区中的类静态属性引用的对象 static3、方法区中常量引用的对象 final4、本地方法栈native引用的对象 native4.2 常用的JVM基本配置参数 JVM的参数类型1、标配参数-version -help -showversion2、X参数了解: -Xint:解释执行 -Xcomp:第一次使用就编译成本地代码 -Xmixed:混合模式3、XX参数重点Boolean类型-XX: 属性值、-XX: - 属性值开启、-关闭例-XX:PrintGCDetails 打印GC日志-XX:UseSerialGC 、-XX:-UseG1GC 打开/关闭某垃圾收集器java -XX:PrintFlagsInitial 查看JVM所有初始化参数java -XX:PrintFlagsFinal 查看JVM所有修改、更新后的参数java -XX:PrintCommandLineFlags -version 查看内存空间初始值KV设值类型-XX:keyvalue常见参数 -XX:NewSize10m 新生代 -XX:OldSize60m 老年代 -XX:PermSize50m 永久代 -XX:MaxPermSize50m 永久代最大内存 -XX:MetaspaceSize128 元空间, 理论上取决于物理内存,实际只有20MB左 -XX:MaxTenuringThreshold15 控制对象在经过多少次minor GC之后进入老年代此参数只有在Serial 串行GC时有效。-Xms: 堆初始内存大小默认为物理内存的1/64等价于 -XX:InitialHeapSize -Xmx: 堆最大内存大小默认为物理内存的1/4 等价于 -XX:MaxHeapSize -Xmn: 设置年轻代的大小默认为堆内存的1/3 等价于 -XX:NewSizen -XX:SurvivorRatio3: Eden区 / Survivor区3 (PS:年轻代有2个Survivor区) -XX:NewRatio3: 年轻代Young / 老年代Old3案例一查看某个程序配置项信息jinfo -flag 配置项 进程号 ​ 查看某个程序所有配置项信息jinfo -flags 进程号 案例二查看本机MetaspaceSize大小并修改为256MB 1、jps -l 查询后台运行的进程号码 2、jinfo -flag MetaspaceSize 1030 指定进程号的配置项信息 3、修改 4、再次测试修改成功 查看系统默认参数 第一种 1、jps -l 查看本机后台java进程信息 2、jinfo -flag 配置项 进程号 查看某个进程配置项相关信息 3、jinfo -flags 进程号 查看某个进程所有配置项信息第二种 1、Java -XX:PrintFlagsInitial 查看JVM所有初始化参数 2、Java -XX:PrintFlagsFinal 查看JVM所有修改、更新后的参数 JVM默认加载 : 用户修改的 3、java -XX:PrintFlagsFinal -XX MetaspaceSize512m T 运行时参数修改 4、java -XX:PrintCommandLineFlags -version 查看内存空间初始值初始垃圾回收器总结 查看初始垃圾回收器jinfo -flags进程号java -XX:PrintCommandLineFlags -version 查看某个初始配置项参数值jps -l 查看本机后台java进程信息jinfo -flag 配置项 进程号 查看某个进程配置项相关信息4.3 垃圾收集算法与垃圾回收器 四大垃圾回收算法引用计数法、复制算法、标记清除、标记整理 落地实现串行Serial、并行Parallel、并发CMS、G1 七大垃圾回收器UseSerialGC、UseParNewGC、UseParallelGC – 新生代 UseSerialOldGC、UseConcMarkSweepGC、UseParallelOldGC、UseG1GC -老年代 case1:查看本机使用的垃圾收集器java -XX:PrintCommandLineFlags -versioncase2:配置串行Serial收集器 (年轻代UseSerialGC串行 老年代UseSerialOldGC串行)-Xms10m -Xmx10m -XX:PrintGCDetails -XX:PrintCommandLineFlags -XX:UseSerialGCcase3:配置并行ParNew收集器不推荐使用后老年代使用CMS(年轻代UseParNewGC并行 老年代UseSerialOldGC串行) -Xms10m -Xmx10m -XX:PrintGCDetails -XX:PrintCommandLineFlags -XX:UseParNewGCcase4:配置并行Parallel收集器(年轻代UseParallelGC并行 老年代UseParallelOldGC并行) -Xms10m -Xmx10m -XX:PrintGCDetails -XX:PrintCommandLineFlags -XX:UseParallelGCcase5:配置并发CMS收集器(年轻代UseParNewGC并行 老年代UseConcMarkSweepGC并行) -Xms10m -Xmx10m -XX:PrintGCDetails -XX:PrintCommandLineFlags -XX:UseConcMarkSweepGCcase6:配置G1集器-Xms10m -Xmx10m -XX:PrintGCDetails -XX:PrintCommandLineFlags -XX:UseG1GC怎么选择垃圾收集器? 1.优先调整堆的大小让服务器自己来选择 2.如果单核CPU或小内存(100m), 使用串行收集器Serial、Serial old 3.如果多核CPU需要最大吞吐量如后台计算型引用 使用并行收集器Parallel、Parallelold 4.如果多核CPU需要低停顿时间如需快速响应的电商 使用并发收集器CMS、ParNew 官方推荐G1,性能高。4.4 Linux系统变慢如何定位 整机-内存-磁盘-CPU-IO a、查看整体机器性能 top 分析过程cpu/mem-id-load avg1、先整体查看cpu 与mem内存占用率是否存在某个线程占用的cpu或内存太高。2、再单个CPU占用率因为现在都是多核cpu按数字1着重查看ididle cpu空闲率id越大越好3、最后查看load average系统负载率分别是1分钟5分钟15分钟的系统平均负载率load average2.332.512.12 如果abc/36,说明系统负载率太高。b、查看内存信息 free -mfreefree -gfree -m以MB字节查看内存信息c、查看磁盘信息 df -h d、查看包含但不限于CPU也有内存 vmstat -n 2 3 e、查看磁盘IO信息 iostat -xdk 2 34.5 Github骚操作 in、stars、forks、#L、location、language 1、通过in关键词限制搜索范围 java in:name,description,readme 查找项目名name、描述description、readme中包含关键字java的github项目2、通过 stars 或者forks数 去查找项目java stars:2000..5000 forks:20..50 查找点赞数stars在[2000,5000],收藏fork数[20,50]的java项目java stars:5000 forks:20 查找点赞数stars大于5000收藏fork数大于20的java项目 综合springboot项目 in name,description stars:5000 forks:20 pushed:2020-01-01 3、awesome 关键字awesome java 查找关于java的教程精品4、分享项目中某一行的代码 https://github.com/MrZhu1/solidity/blob/master/10-test_Array.sol#L23 高亮显示github关键代码的行号 #L23 https://github.com/MrZhu1/solidity/blob/master/10-test_Array.sol#L23-L27高亮显示github关键代码的段落 #L23-L275、搜索某个地区内的大佬 location:nanjing language:java 查找活跃用户
http://www.zqtcl.cn/news/755388/

相关文章:

  • 小型网站制作网站开发做什么费用
  • seo网站论文社交app开发公司
  • 企业宣传网站建设图示《高性能网站建设》
  • 福州志愿者官方网站怎么做erp管理系统介绍
  • 高端网站建设费用情况广州开发区控股集团有限公司
  • 精湛的网站设计云南网招聘
  • 南昌网站建设公司行情Wordpress添加分页按钮
  • 论坛网站建设流程wordpress速度优化插件
  • PHP套模板做网站建设银行保定分行网站
  • 怎样免费注册网站域名wordpress网站回调域
  • 东莞个人免费建网站乐清网约车事件
  • 备案查询网站网站的登录弹窗怎么做
  • 网站开发 mvc北京建设工程主管部门网站
  • 淮安建设机械网站制作代理公司注册需要多少钱
  • 站长收录茌平建设局网站
  • 如何进行网站开发开发区人才
  • 网站制作 视频网站维护的主要内容包括
  • 快速企业建站深圳网站关键词优化推广
  • 如何开网店详细步骤东莞市网络seo推广
  • 个人可以做哪些有意思的网站网站和网站的app
  • 北京高端网站开发公司网站建设后台实训体会
  • 青岛海川建设集团有限公司网站wordpress 变私有云
  • 网站备案人可以改吗石大网页设计与网站建设客观题
  • 宁波网站优化方案免费关键词挖掘工具
  • 网站制作想法免费做效果图网站
  • 晓风彩票网站建设软件微信上发的链接网站怎么做的
  • 关键词有哪几种台州优秀关键词优化
  • 盐田区住房和建设局网站软件开发文档怎么编写
  • 网站响应式建设seo排名优化怎样
  • 山东 网站备案德清县建设局网站