美文网首页面试题
java面试之四

java面试之四

作者: lijiaccy | 来源:发表于2017-08-07 16:58 被阅读12次
    1、你常用的jvm监控工具或者命令有哪些
    • GC日志 PrintGCDetails 每次GC记录日志
    • jstat -gcutil pid 5s 10//间隔5s,打印10次


      Paste_Image.png

      S0 — Heap上的 Survivor space 0 区已使用空间的百分比
      S1 — Heap上的 Survivor space 1 区已使用空间的百分比
      E — Heap上的 Eden space 区已使用空间的百分比
      O — Heap上的 Old space 区已使用空间的百分比
      M — Metaspace 区已使用空间的百分比
      YGC — 从应用程序启动到采样时发生 Young GC 的次数
      YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
      FGC — 从应用程序启动到采样时发生 Full GC 的次数
      FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
      GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)

    • jstack pid:结合top看看是不是cpu过高,导致死锁
    2、java8的lambda表达式了解过吗?

    java8之前:

    new Thread(new Runnable(){
         public void run() {
             System.out.println(1123);
         }
    }).start();
    

    java8:

        new Thread(() -> System.out.println(123)).start();
    

    还有其他的好多东西,下次找个时间专门研究一下这个。

    3、A,B两个线程同时启动,但让A结束后B在结束,如何实现。

    用join关键字。t.join()方法阻塞调用此方法的线程(calling thread),直到线程t完成,此线程再继续;通常用于在main()主线程内,等待其它线程完成再结束main()主线程。例如:

    public class Test implements Runnable{
    
    private String name;
    
    public Test(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        System.out.println(new Date()+"  "+name);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Test("zhangsan"));
        Thread thread1 = new Thread(new Test("lijia"));
        thread.start();
        thread1.start();
        thread.join();
        thread1.join();
        System.out.println("qqqqqqqqqqqq");
    }
    }
    
    运行结果

    如果把join去掉:

    Paste_Image.png
    4、java中什么是锁

    我认为面试官一般问这种问题都是想问你synchronized。主要是问完这个也会顺带着问Lock。锁里面还有一些概念公平锁、非公平锁、自旋锁、可重入锁、偏向锁、轻量级锁、重量级锁、读写锁、互斥锁等。
    synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

    • 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;

    • 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;

    • 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

    • 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

        public class Test2 {
        public static void main(String[] args) {
        SyncThread syncThread = new SyncThread();
        Thread thread1 = new Thread(syncThread, "SyncThread1");
        Thread thread2 = new Thread(syncThread, "SyncThread2");
        thread1.start();
        thread2.start();
      
        }
        }
       class SyncThread implements Runnable {
         private int count;
         public SyncThread() {
         count = 0;
        }
       public  void run() {
        //        synchronized(this) {
             for (int i = 0; i < 5; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
       //        }
      }
         public int getCount() {
          return count;
         }
      }
      

    运行结果为


    加上synchronized之后

    再没有加锁之前,两个线程相互调用cpu,加锁之后,SyncThread1线程执行完才到SyncThread2,而且保证了正确性。

    那么再说说volatile吧

    还是用上面的例子说明,其他都不动

     private volatile int count;//在count这加入volatile
    

    运行结果

    图片.png 图片.png

    用volatile只能保证可见性,但是不保证原子性。如上图,结果就是不正确的。
    volatile也能禁止重排序

    那么volatile怎么保证可见性和禁止重排序
    引入深入理解java虚拟机中一段话: 观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令
    lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:
    1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
    2)它会强制将对缓存的修改操作立即写入主存;
    3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
    使用volatile必须具备以下2个条件:
    1)对变量的写操作不依赖于当前值
    2)该变量没有包含在具有其他变量的不变式中
    也会说道Lock和AQS,请看
    http://www.jianshu.com/p/d333d5177498
    也许会问JUC下的一些其他类,这里不说了。

    相关文章

      网友评论

        本文标题:java面试之四

        本文链接:https://www.haomeiwen.com/subject/wwfpkxtx.html