这家公司是先笔试再面试,笔试共二十五题,Java基础只占一小部分,三成左右吧,有很多是多线程和数据库,这家公司多数据库非常看重,要求面试者必须会数据库。我下面把我觉得有价值的笔试题和面试题总结在下面。
博客
简单地说,String是不可变字符串,另外两个是可变字符串,StringBuffer有一个用了synchronized关键字修饰,是线程安全的,但效率也会下降,StringBuilder是线程不安全。
我觉得创建一个HashMap,再将字符作为键,出现次数作为值存放进去。
两个对象相互equals,则hashcode一定相同;如果重写了equals方法,则hashcode方法也要重写,为的是保证一致性。
Java有5种方式来创建对象:
ObjectName obj = new ObjectName();
ObjectName obj = ObjectName.class.newInstance();
ObjectName obj = ObjectName.class.getConstructor.newInstance();
ObjectName obj = obj.clone();
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_NAME))) {
ObjectName obj = ois.readObject();
}
引用自博客。
老生常谈,必会的问题。
ThreadLocal的实例代表了一个线程局部的变量,每条线程都只能看到自己的值,并不会意识到其它的线程中也存在该变量。
它采用采用空间来换取时间的方式,解决多线程中相同变量的访问冲突问题。
线程安全指的是,在堆内存中的数据由于可以被任何线程访问到,在没有限制的情况下存在被意外修改的风险。即堆内存空间在没有保护机制的情况下,对多线程来说是不安全的地方,因为你放进去的数据,可能被别的线程“破坏”。
HashTable,Vector,ConcurrentHashMap……
网上搜到的资料
CyclicBarrier和CountDownLatch 都位于java.util.concurrent 这个包下,用于多线程。
CountDownLatch | CyclicBarrier |
---|---|
减计数方式 | 加计数方式 |
计算为0时释放所有等待的线程 | 计数达到指定值时释放所有等待线程 |
计数为0时,无法重置 | 计数达到指定值时,计数置为0重新开始 |
调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响 | 调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞 |
不可重复利用 | 可重复利用 |
堆:主要用于存储实例化的对象,数组。由JVM动态分配内存空间。一个JVM只有一个堆内存,线程是可以共享数据的。
栈:主要用于存储局部变量和对象的引用变量,每个线程都会有一个独立的栈空间,所以线程之间是不共享数据的。
详细的看这里
《核心技术》上这样说,“构建一个新的线程是有一定代价的,因为涉及与操作系统的交互。如果程序中创建了大量的生命期很短的线程,应该使用线程池(thread pool)。”线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。
RuntimeException是Exception的子类,关系如下图
常见的RuntimeException:
ArithmeticException(算术异常)
ClassNotFoundException(类没找到时,抛出该异常)
FileNotFoundException(文件未找到异常)
SQLException(操作数据库异常)
NullPointerException(空指针异常)
引用这篇文章。
这个问题前面已经总结过好几次了,这里就不再赘述了。
倒排索引,IK分词器
这个问题也在之前的文章里总结过了,不多说。
元数据区取代了原来的永久代。
不能,看这里
一样不再多说。