那些你没去深入了解的JAVA知识

  1. Thread start 方法和 run 方法到底哟哟什么区别?
  2. Thread 只是一个线程类的管理,而不是实现,更不是抽象!
  • 两个方法均唤起了 其维护的target (也就是一个 Runable 接口的实现)的run方法,最大的区别是 直接调 run 方法还是在当前线程执行的,而start 才是另起一个县城执行
  • Thread 的start 方法: 做的工作包括 : 1. 维护了这个子线程的状态 2. 将线程(Thread) 添加到线程组中 3 : 通过调用 本地方法start0()开启 子线程执行
  1. 解释下Tomcat 处理请求的线程模型
  • 收到一个请求就新开一个线程去处理任务,主线程返回,继续处理下一个任务,这样解解决了主线程的阻塞问题
  • Tomcat 维护一个处理请求线程的线程池
  • 一旦有请求,Tomcat会初始化minSapreThreads设置的线程数;
  1. 怎么检测一个线程是否持有对象监视器
    Thread类提供了一个holdsLock(Object obj)方法,当且仅当对象obj的监视器被某条线程持有的时候才会返回true,注意这是一个static方法,这意味着“某条线程”指的是当前线程。

  2. 为什么wait,notify()notifyAll()两个方法放在了Object下面而不是Thread下面?

    • 这三个方法其实都是属于锁的,而每个锁恰好都是对象(Object)
    • 基于以上条件,所以这三个方法都需要在同步代码块里面调用,因为只有在对同步代码块中,锁对象的锁才是有效的
  3. 为什么String被设计为final类?

    • 因为String是默认被缓存到JVM的String Pool中,String 对象会被多个Client共享,如果一个Client修改了String会导致其他Client出现错误
    • String不支持继承的另一个原因是就是防止修改其hashcode和equals 方法,因为这两个方法太重要了!
  4. Java yield,wait,sleep之间的区别

  • yield :释放CPU资源给线程调控器,调用yield()方法后的线程,在后续也很有可能会获取到CPU资源,继而继续执行线程中的方法
  • sleep:相对于yield来说,并不会释放CPU资源,它只是sleep而已
  • wait,notify 这样的方法是属于锁的,跟sleep和yiled不同,他们是并发模型的实现!
  1. Java 枚举实现的原理
    参考文章

  2. 方法中向匿名类传递参数,为什么需要将参数设置为final?

    1. 匿名内部类不能含有构造函数和 静态对象,静态方法
      匿名内部类在编译时,像其他内部类一样被编译为一个class文件,
      简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。故如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。
  3. 方法锁、对象锁和类锁的意义和区别?
    参考

  4. StringBuilder 和 String.concat的性能比较

    1. 参考

    2. 性能参考

    3. Java中字符串拼接不要直接使用+拼接。一般Java Complier会直接将+ 优化为new 一个 Stringbuilder 和 toString两个补奏

    4. 使用StringBuilder或者StringBuffer时,尽可能准确地估算capacity,并在构造时指定,避免内存浪费和频繁的扩容及复制。如果不指定StringBuilder的话,每次容量达到临界值,StringBuilder会将容量double容量,这样的话会很浪费
      在没有线程安全问题时使用StringBuilder, 否则使用StringBuffer。
      两个字符串拼接直接调用String.concat性能最好。

      经实践发现,concat也会被StringBuilder的append

  5. 静态代码块、构造代码块、构造函数以及Java类初始化顺序
    1. 类被加载时,静态代码块执行
    2. 对象初始化时,构造代码块执行,且优先于构造函数执行

  6. Java中的对象引用
    在Java中,对于原始类型变量保存的是真正的value,对于Object变量来说,变量保存的都是指向对象的指针。。映射到集合中
    相对于方法传递来说,对于
    1. 如果参数是基本类型,传递的是基本类型的字面量值的拷贝。
    2. 如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。
    对于添加到内存中也是类似
    (1)如果是基本数据类型,则是value
    (2) 如果是复合数据类型,则是引用的地址;String b="a"; lists.add(b); b="bbb";最后输出还是a,
    原因是存放的不是b,而是b第一次指向的地址,修改b=”bbb”后只是修改了b指向的地址。

  7. Java 中的浮点型问题
    https://stackoverflow.com/questions/13467849/double-multiplied-by-100-and-then-cast-to-long-is-giving-wrong-value)

你可能感兴趣的:(那些你没去深入了解的JAVA知识)