周阳面试JUC和JVM


** 作为自己复习和分享**

1.2019年4月份版本JUC(java.util.concurrent)

1.1进程/线程

进程:是一个程序运行的最小单位(巧记:先“进”来,然后才能看到线程)
线程:是进程里最小的运行单位(例如idea进程,里面有多个微服务在运行,就是线程)

1.2并发/并行

并发:
在相对的一段时间内,其实是很短,对计算机有感,对人无感,多个线程抢占资源来执行自
己 ,执行A一段时间,马上执行B,然后执行C,以此类推,这几个线程对人来说可以看成
是“同时”完成的,也即并发,但对机器来说就是时间错开运行的。
并行:
多个线程在相同的时间内同时运行。

1.3 三个包

java.util.concuurent
java.util.concuurent.atomic
java.util.concuurent.locks

1.4JUC强大的辅助类

1.4.1countDownLatch

package ticket;

import java.util.concurrent.CountDownLatch;

public class CountDown {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);

        for (int i = 1; i <= 6 ; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "离开教室");
                countDownLatch.countDown();
            },String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println("班长离开教室");
    }
}

原理
在这里插入图片描述
** 1.4.2cyclicBarrie**
人到齐了再开会

package ticket;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CountDown {
    public static void main(String[] args) throws InterruptedException {
        CyclicBarrier barrier = new CyclicBarrier(7, () -> {
            System.out.println("召唤神龙");
        });

        for (int i = 1; i <= 7 ; i++) {
            final int tempInt = i;
            new Thread(() -> {
                System.out.println("第"+tempInt+ "颗龙珠");
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }

}

** 1.4.3信号灯semaphore **
在这里插入图片描述

package ticket;

import java.util.concurrent.Semaphore;

public class CountDown {
    public static void main(String[] args) {

        Semaphore semaphore = new Semaphore(3);

        for (int i = 1; i <= 6 ; i++) {
            final int tem = i;
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println("第"+tem+"辆车停入车库");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("第"+tem+"辆车离开车库");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                }

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

        }

    }

}

1.5 读写分离 ReentrantReadWriteLock

读读可共享,写读和写写中写独占
读读能共存,读写,写写都不能共存

2.售票多线程

题目:三个售票员,卖出 ,30张票
笔记:如何编写企业级的多线程代码
固定的编程套路+模板是什么?
1.在高内聚低耦合的前提下,线程 操作 资源类。
1.1 一言不合,先创建一个资源类
1.2 一个线程start之后不是马上就启动,调度跟底层的cup有关系
1.3多线程有哪几种状态Thread.State看api即可,有六种
NEW、RUNNABLE、BLOCKED、WAITING(死等)、TIMED_WAITING(过时不候)、TERMINATED

class Ticket{ //资源类 = 实例变量+实例方法
           private int number = 120;
        Lock lock = new ReentrantLock();
        public void sale(){
            lock.lock();
            try {
                if(number > 0) {
                    System.out.println(Thread.currentThread().getName()+"\t卖出第:"+(number--)+"\t还剩:"+number);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }

        }
    }

    public class SaleTicket {

        public static void main(String[] args) {
            Ticket ticket = new Ticket();
            /*new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i <=40 ; i++) {
                        ticket.sale();
                    }
                }
            }, "A").start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i <=40 ; i++) {
                        ticket.sale();
                    }
                }
            }, "B").start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i <=40 ; i++) {
                        ticket.sale();
                    }
                }
            }, "C").start();*/
            //使用lambda表达式之后只用三行代码
            new Thread( () -> {for (int i = 0; i <=40 ; i++) ticket.sale();} ,"A").start();
            new Thread( () -> {for (int i = 0; i <=40 ; i++) ticket.sale();} ,"B").start();
            new Thread( () -> {for (int i = 0; i <=40 ; i++) ticket.sale();} ,"C").start();

        }

3.lambda表达式简单复习

3.1 函数式编程
3.1.1拷贝小括号 , 中间右箭头,落地大括号
3.1.2
@FunctionalInterface(使用这个注解的接口一定是函数式接口)
函数式接口里可以有除了唯一方法之外的默认方法
静态方法
default static

package lambda;

@FunctionalInterface
interface Foo {
//    public void sayHello();
    int add(int x, int y);
    default int plus(int x, int y){
        return x + y;
    }
    public static int div (int x, int y){
        return x/y;
    }
}

public class LambdaTest {

    public static void main(String[] args) {
//        Foo foo = () -> { System.out.println("lambda函数式编程");};
        Foo foo = (int x , int y) -> {
            System.out.println("两数之和");
            return  x + y;
        };

        System.out.println(foo.add(6, 9));
    }
}

4.集合类不安全

4.1 故障现象(并发修改异常)
java.util.ConcurrentModificationException
4.2导致原因
多线程并发,资源未加锁
4.3解决方法
1.Vector是线程安全的,加了锁
2.Collections.synchronizedList(new ArrayList());
3.new CopyOnWriteArrayList(); (写时复制)
4.4优化建议(同样的错误不犯第二次)
高并发下推荐使用juc里的
4.5常用集合相对的安全的集合
HashMap -> ConcurrentHashMap
HashSet -> CopyOnWriteArraySet
ArrayList -> CopyOnWriteArrayList

5.八锁原理讲解

以手机发短信和邮件为场景
1.标准访问,先打印邮件还是短信?

先邮件后短信
静态方法锁的是类,普通方法锁的是对象
phone里的锁,会把这个对象给锁住,只要有一个线程进来访问,那么其他线程就都进不来。
class Phone{
    public synchronized void sendEmainl()throws Exception{
        System.out.println("sendEmail");
    }
    public synchronized void sendSMS()throws Exception{
        System.out.println("sendSMS");
    }
}

public class BaSuo {

    public static void main(String[] args) throws Exception{
        Phone phone = new Phone();
        new Thread(() -> {
            try {
                phone.sendEmainl();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(() -> {
            try {
                phone.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}
  1. 暂停4秒钟邮件方法,请问先打印邮件还是短信?
先邮件后短信
class Phone{
    public synchronized void sendEmainl()throws Exception{
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }
    public synchronized void sendSMS()throws Exception{
        System.out.println("sendSMS");
    }
}

public class BaSuo {

    public static void main(String[] args) throws Exception{
        Phone phone = new Phone();
        new Thread(() -> {
            try {
                phone.sendEmainl();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(() -> {
            try {
                phone.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

3.新增普通sayHello方法,请问先打印邮件还是hello?

先hello后邮件
普通方法不会和加锁的方法争抢资源,所以不会被锁
package basuo;

import java.util.concurrent.TimeUnit;

class Phone{
    public synchronized void sendEmainl()throws Exception{
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }
    public synchronized void sendSMS()throws Exception{
        System.out.println("sendSMS");
    }
    public  void sayHello()throws Exception{
        System.out.println("sayHello");
    }
}

public class BaSuo {

    public static void main(String[] args) throws Exception{
        Phone phone = new Phone();
        new Thread(() -> {
            try {
                phone.sendEmainl();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(() -> {
            try {
//                phone.sendSMS();
                phone.sayHello();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

4.两部手机,先打印邮件还是短信?

先短信后邮件
package basuo;

import java.util.concurrent.TimeUnit;

class Phone{
    public synchronized void sendEmainl()throws Exception{
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }
    public synchronized void sendSMS()throws Exception{
        System.out.println("sendSMS");
    }
    public  void sayHello()throws Exception{
        System.out.println("sayHello");
    }
}

public class BaSuo {

    public static void main(String[] args) throws Exception{
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        new Thread(() -> {
            try {
                phone.sendEmainl();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(() -> {
            try {
                phone2.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

5.两个静态同步方法,先打印邮件还是短信?

先邮件后短信
对象锁和全局锁的区别,静态同步方法是全局锁,把Class锁了
package basuo;

import java.util.concurrent.TimeUnit;

class Phone{
    public static synchronized void sendEmainl()throws Exception{
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }
    public static synchronized void sendSMS()throws Exception{
        System.out.println("sendSMS");
    }
    public  void sayHello()throws Exception{
        System.out.println("sayHello");
    }
}

public class BaSuo {

    public static void main(String[] args) throws Exception{
        Phone phone = new Phone();
        new Thread(() -> {
            try {
                phone.sendEmainl();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(() -> {
            try {
                phone.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

6.两个静态同步方法,两部手机,先打印邮件还是短信?

先邮件后短信
package basuo;

import java.util.concurrent.TimeUnit;

class Phone{
    public static synchronized void sendEmainl()throws Exception{
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }
    public static synchronized void sendSMS()throws Exception{
        System.out.println("sendSMS");
    }
    public  void sayHello()throws Exception{
        System.out.println("sayHello");
    }
}

public class BaSuo {

    public static void main(String[] args) throws Exception{
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        new Thread(() -> {
            try {
                phone.sendEmainl();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(() -> {
            try {
                phone2.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

7.一个静态同步方法,一个普通同步方法,同一部手机,结果?

先短信后邮件
package basuo;

import java.util.concurrent.TimeUnit;

class Phone{
    public static synchronized void sendEmainl()throws Exception{
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }
    public synchronized void sendSMS()throws Exception{
        System.out.println("sendSMS");
    }
    public  void sayHello()throws Exception{
        System.out.println("sayHello");
    }
}

public class BaSuo {

    public static void main(String[] args) throws Exception{
        Phone phone = new Phone();
        new Thread(() -> {
            try {
                phone.sendEmainl();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(() -> {
            try {
                phone.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

8.一个静态同步方法,一个普通同步方法,两部手机,结果?

先短信后邮件
package basuo;

import java.util.concurrent.TimeUnit;

class Phone{
    public static synchronized void sendEmainl()throws Exception{
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }
    public synchronized void sendSMS()throws Exception{
        System.out.println("sendSMS");
    }
    public  void sayHello()throws Exception{
        System.out.println("sayHello");
    }
}

public class BaSuo {

    public static void main(String[] args) throws Exception{
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        new Thread(() -> {
            try {
                phone.sendEmainl();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"A").start();
        Thread.sleep(100);
        new Thread(() -> {
            try {
                phone2.sendSMS();
            }catch (Exception e){
                e.printStackTrace();
            }
        },"B").start();
    }
}

6生产者消费者

题目:现在两个线程,可以操作初始值为零的一个变量,实现一个线程对该变量加1,一个线程对该变量减1,实现交替,来10轮,变量初始值为零。
1. 高内聚低耦合前提下,线程操作资源类
2. 判断 执行 通知
3. 防止线程的虚假唤醒(多线程里,条件判断不可以用if要用while)

package prodconsumer;
class Aircondition{
    private int number = 0;
    public synchronized void increment() throws InterruptedException {

        //1.判断(if要改成while就不会有虚假唤醒)
        while (number != 0) {
            this.wait();
        }
        //2.干活
        number ++ ;
        System.out.println(Thread.currentThread().getName() + "\t" + number);
        //3.通知
        this.notifyAll();
    }
    public synchronized void decrement() throws InterruptedException {
        //1.判断
        while (number == 0) {
            this.wait();
        }
        //2.干活
        number -- ;
        System.out.println(Thread.currentThread().getName() + "\t" + number);
        //3.通知
        this.notifyAll();

    }
}

public class ProdConsumer {
    public static void main(String[] args) {
        Aircondition aircondition = new Aircondition();

        new Thread(() -> {
            for (int i = 0; i <10 ; i++) {
                try {
                    aircondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"A").start();

        new Thread(() -> {
            for (int i = 0; i <10 ; i++) {
                try {
                    aircondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
        new Thread(() -> {
            for (int i = 0; i <10 ; i++) {
                try {
                    aircondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"C").start();

        new Thread(() -> {
            for (int i = 0; i <10 ; i++) {
                try {
                    aircondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"D").start();
    }
}

生产者消费者2

package prodconsumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Aircondition{
    private int number = 0;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public  void increment() throws InterruptedException {

        lock.lock();
        try {
            //1.判断
            while (number != 0) {
                condition.await();
            }
            //2.干活
            number ++ ;
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            //3.通知
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public  void decrement() throws InterruptedException {

        lock.lock();
        try {
            //1.判断
            while (number == 0) {
                condition.await();
            }
            //2.干活
            number -- ;
            System.out.println(Thread.currentThread().getName() + "\t" + number);
            //3.通知
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

}

public class ProdConsumer {
    public static void main(String[] args) {
        Aircondition aircondition = new Aircondition();

        new Thread(() -> {
            for (int i = 0; i <10 ; i++) {
                try {
                    aircondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"A").start();

        new Thread(() -> {
            for (int i = 0; i <10 ; i++) {
                try {
                    aircondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
        new Thread(() -> {
            for (int i = 0; i <10 ; i++) {
                try {
                    aircondition.increment();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"C").start();

        new Thread(() -> {
            for (int i = 0; i <10 ; i++) {
                try {
                    aircondition.decrement();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"D").start();
    }
}

7.condition例子

题目:多线程之间按顺序调用,实现A->B->C
三个线程启动,要求如下:
A打印5次,B打印10次,c打印15次
接着
A打印5次,B打印10次,c打印15次
循环10轮

package prodconsumer;


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//资源类
class ConditionDemo1{
    private int number = 1; //A :1 B :2 C :3
    private Lock lock = new ReentrantLock();
    private java.util.concurrent.locks.Condition condition1 = lock.newCondition();
    private java.util.concurrent.locks.Condition condition2 = lock.newCondition();
    private java.util.concurrent.locks.Condition condition3 = lock.newCondition();

    public void print5(){
        lock.lock();
        try {
//            1.判断
            while (number != 1){
                condition1.await();
            }
//            2.执行
            for (int i = 0; i <5 ; i++) {
                System.out.println(Thread.currentThread().getName() + "\t:" + i);
            }
//            3.通知
            number = 2;
            condition2.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void print10(){
        lock.lock();
        try {
//            1.判断
            while (number != 2){
                condition2.await();
            }
//            2.执行
            for (int i = 0; i <10 ; i++) {
                System.out.println(Thread.currentThread().getName() + "\t:" + i);
            }
//            3.通知
            number = 3;
            condition3.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void print15(){
        lock.lock();
        try {
//            1.判断
            while (number != 3){
                condition3.await();
            }
//            2.执行
            for (int i = 0; i <15 ; i++) {
                System.out.println(Thread.currentThread().getName() + "\t:" + i);
            }
//            3.通知
            number = 1;
            condition1.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

}

public class Condition {
    public static void main(String[] args) {

        ConditionDemo1 conditionDemo1 = new ConditionDemo1();

        new Thread( () -> {
            for (int i = 0; i <10 ; i++) {
                conditionDemo1.print5();
            }
        },"A").start();
        new Thread( () -> {
            for (int i = 0; i <10 ; i++) {
                conditionDemo1.print10();
            }
        },"B").start();
        new Thread( () -> {
            for (int i = 0; i <10 ; i++) {
                conditionDemo1.print15();
            }
        },"C").start();
    }
}

8.callabe

实现线程的第三种方法

package prodconsumer;


import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

class MyThred implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        System.out.println("******Mythread name call******");
        return 1024;
    }
}

public class CallableDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask(new MyThred());

        new Thread(futureTask,"A").start();
        Integer integer = futureTask.get();
        System.out.println(integer);

    }
}

1.get方法一般放在最后

9.JVM

9.1JVM架构图

在这里插入图片描述

9.2类加载器

在这里插入图片描述

9.2.1加载器类型

1.虚拟机自带的加载器
启动类加载器(Bootstrap)C++ (返回为null)
扩展类加载器(Extension)Java
应用程序加载器(AppClassLoader)也叫系统列加载器,加载当前应用的的classpath的所有类(返回为appcalssloader)
2.用户自定义加载器
Java.lang.ClassLoader的子类,用户可以定制类的加载方式
在这里插入图片描述

9.2.2双亲委派机制

一句话,我爸是李刚,有事找他(哈哈哈)-----------老师说

理论解释:
当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在他的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。
采用双亲委派的一个好处是比如加载位于rt.jar包中的类java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个Object对象。
双亲委派机制保证了沙箱安全。

9.3本地方法

native 放在本地方法栈(native method stack)

9.4PC寄存器

程序计数器(Program counter register)
记录了方法之间的调用和执行情况,类似排班值日表
可以理解成一个指针,指向下一个应该执行的程序
如果执行native方法,那么计数器为空

9.5方法区

供各线程共享的运行时内存区域。**他存储了每一个类的结构信息,例如运行时常量池(Runtime Constant Pool)、字段和方法数据、构造函数和普通方法的字节码内容。
上面讲的是规范,在不同虚拟机里面实现是不一样的,最典型的就是永久代(Permgen space)和元空间(Metaspace)
** 但是

实例变量存在堆内存中,和方法区无关

9.6java栈

栈管运行,堆管存储
程序 = 算法 + 数据结构
程序 = 框架 + 业务逻辑

9.6.1栈内存

主管java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就over,生命周期和线程一致,是线程私有的。
8种基本类型的变量+对象的引用变量+实例方法都是在函数的栈内存中分配

栈+堆+方法区的交互关系

在这里插入图片描述

9.7堆

  • 堆、heap
    • 1.新生代 NEW
      • 1.伊甸区(Eden区)
        在这个阶段GC,称为YGC或轻量GC
      • 2.幸存者0区(survivor 0 sapce)
      • 3.幸存者1区 (survivor 1 space)
    • 2.老年代 Old
      这里满了之后开启full GC = FGC
    • 3.元空间

堆物理上分两部分:新生代+老年代
堆内存逻辑上分三部分:新生代+ 老年代+元空间

9.8对象的生命周期

幸存者0区也叫from区,幸存者1区也叫to区
form和to两个区位置和名称不是固定的,每次GC之后会交换,交换之后,谁是空的谁是to、
在这里插入图片描述

9.9堆参数调优入门

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
FullGC(这张图太长了,后边的缺失部分和GC一致)
在这里插入图片描述

9.10GC是什么(分代收集算法)

  • 次数上频繁收集Yong区
  • 次数上较少收集Old区
  • 基本不动元空间

9.11GC收集算法

  • GC和FullGC不是同时执行
  • FullGC的运行一次是GC的10倍左右,因为fullGC清理的空间比GC要清理的空间大
  • 四种算法
    • 1.引用计数法
      在这里插入图片描述

    • 2.复制算法(Copying)

      • 年轻代中使用的是Minor GC,这种算法采用的是复制算法
      • 是什么
        在这里插入图片描述
      • 劣势
        1.浪费了一般的内存
    • 3.标记清除(Mark-Sweep)

      • 老年代一般由标记清除或者标记清除与标记整理的混合实现
      • 是什么 在这里插入图片描述
      • 劣势
        • 两次扫描,耗时严重
        • 会产生内存碎片
    • 4.标记压缩(Mark-Compact)(标记整理)

      • 老年代一般是由标记清除或者是标记清除与标记整理的混合实现
      • 是什么 在这里插入图片描述
      • 劣势
        标记整理算法唯一的缺点即使效率也不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址。
        从效率上来说,标记整理算法要低于复制算法
      • 标记清除压缩(Mark - Sweep - Compact)

9.11.1小总结

  • 内存效率:复制算法>标记清除算法>标记整理算法(这里的效率只是简单的对比时间复杂度,实际情况不一定如此)
  • 内存整齐度:复制算法=标记整理算法>标记清除算法
  • 内存利用率:标记整理算法=标记清除算法>复制算法

9.11.2面试题

  • 1.jvm内存模型以及分区,需要详细到每个分区放什么
  • 2.堆里面的分区:Eden,survivalfrom to,老年代,各自的特点
  • 3.GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方
  • 4.Minor GC 与 Full GC分别在什么时候发生

10.JMM(Java 内存模型)

在这里插入图片描述
在这里插入图片描述

10.1可见性

10.2原子性

10.3volatiledemo代码演示可见性+原子性

10.4有序性

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值