GC算法,阻塞队列,线程池拒绝策略

有关GC

GC的算法就是分代收集算法,就是什么区适合用什么算法就用什么算法。
JVM在进行GC的时候,并非对着堆的三个区域一起回收的,大部分的时候在回收新生区,因此GC按照回收的区域分为轻GC(又叫普通GC)和FullGC(又叫重GC)。
普通GC只针对于新生区域的GC,指发生在新生区的垃圾回收,因为java的对象存活率不高,所以轻GC非常频繁,回收速度也快。
重GC指的是发生在养老区的垃圾回收动作,出现重GC经常会伴随至少一次的轻GC,重GC的速度一般比轻GC要慢上10倍。

GC的算法:

可达性算法

将“GC Roots”对象作为起点,从这个节点开始向下搜索引用的对象,找到的对象都被标记为非垃圾对象,其余未标记的对象都是垃圾对象

引用计数法

每次对象引用就有计数器加一,当计数器为零就清除对象。缺点:较难处理循环引用,每次给对象赋值都要维护计数器。

复制算法

基本思想就是将内存分为两块,每次用其中的一块,当这一块内存用完,就将未处理的对象复制到另一块内存上。优点:不会产生内存碎片。缺点:占用空间

标记清除

分成标记和清除两个阶段,先标记要回收的对象,然后统一回收这些对象。缺点:耗时严重,会产生内存碎片;优点:节省空间

标记压缩

又叫标记清除压缩,解决了标记清除的内存碎片的问题,但是耗时,在原有的基础上再次扫描对内存进行压缩。

新生区主要使用复制算法,养老区主要使用标记清除和标记压缩混合实现。

Volatile 是java虚拟机提供的轻量级的同步机制。

JMM:java内存模型。每个线程创建的时候,JVM会为其分配一个工作内存空间,每个线程的工作内存空间都是相互独立的,而javade内存模型中规定所有的变量都储存在主内存之中,但线程对变量的操作必须在其工作内存之中,所以每次操作的时候,都会将主内存中的变量拷贝到自己的工作内存之中,然后对其进行操作,操作完再写回到主内存当中,线程的通信必须靠主内存完成。
GC算法,阻塞队列,线程池拒绝策略_第1张图片

使用Callable创建线程细节:get方法写在代码的最后,因为get方法很耗时。

CountDownLatch:规定一个数往下减少
GC算法,阻塞队列,线程池拒绝策略_第2张图片
CyclicBarrier:规定到一个数执行什么

public class cyclicBarrier {
    public static void main(String[] args) {
        //CyclicBarrier是逐步加一的操作,
        // 到达设置的数时会执行函数里的东西
        CyclicBarrier barrier = new CyclicBarrier(7, () -> {
            System.out.println("召唤神龙");
        });
        for (int i = 1; i <= 7; i++) {
          int t=i;
          new Thread(()->{
              System.out.println(t+"个龙珠");
            try {
                //相当于一个通知只要,到了设定的数就执行输出神龙
                  barrier.await();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              } catch (BrokenBarrierException e) {
                  e.printStackTrace();
              }
          }).start();

        }
    }
}

Semaphore:规定只能几个线程运行

//Semaphore的作用就是限流,一次规定线程数
public class CarFight {
    public static void main(String[] args) {
        //设置三个车位
        Semaphore semaphore = new Semaphore(3);
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();//执行只有三个车位的规定
                    System.out.println(Thread.currentThread().getName()+"抢到了车位");
                    TimeUnit.SECONDS.sleep(2);
                    System.out.println(Thread.currentThread().getName()+"离开了车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                 //使用完后需要释放,去唤醒等待的线程,不然会造成死等
                 semaphore.release();
                }

            },String.valueOf(i)).start();
        }

    }
}

ReadWriteLock:读写锁,比lock更细粒度的锁。
写锁上锁
GC算法,阻塞队列,线程池拒绝策略_第3张图片

读锁上锁:
GC算法,阻塞队列,线程池拒绝策略_第4张图片

阻塞队列

当队列为空时,从队列中获取元素会被阻塞;当队列满了的时候,从队列添加元素会被阻塞。

GC算法,阻塞队列,线程池拒绝策略_第5张图片
BlockingQueue是一个接口,有很多实现类。当队列满的时候使用add会抛出异常,当队列空的时候,remove删除元素,或者看队首元素element的时候会抛出异常。当队列满的时候使用offer插入元素的时候会返回false,当没有元素用poll删除的时候会返回一个null,使用peek查看队首元素的时候会返回null。队列满的时候使用put会阻塞,直到有线程出队列,没有元素可删除的时候使用take也会阻塞等待有线程删除。offer还可以设置超时不候功能,当满了offer的时会等待设置时间,过了就不添加了,同理poll也是。

线程池的特点:线程复用,方便管理线程,控制最大并发数。
创造线程使用ThreadPoolExecutor
有七个参数GC算法,阻塞队列,线程池拒绝策略_第6张图片
执行流程:
GC算法,阻塞队列,线程池拒绝策略_第7张图片
首先将corepool放满,然后再去阻塞队列等候,如果再来线程就会开启最大的线程容量,此时阻塞队列等候的线程先执行,后来的接着等候,如果阻塞队列和最大线程容量都满了,就采取拒绝策略不要线程进入了。

你可能感兴趣的:(java,jvm,thread)