1、请你说说多线程

得分点: 线程和进程的关系、为什么使用多线程

进程是操作系统资源调度的基本单位,线程是处理器任务调度和执行的基本单位,一个进程可以创建多个线程,每个线程有自己独立的程序计数器,本地方法栈和虚拟机栈,线程之间共享进程的堆和方法区。

线程之间是通过时间片算法来争夺CPU的执行权的。

多线程的好处:当一个线程进入阻塞或者等待状态时,其他的线程可以获取CPU的执行权,提高了CPU的利用率。

多线程的缺点:可能产生死锁;频繁的上下文切换可能会造成资源的浪费;在并发编程中如果因为资源的限制,多线程串行执行,可能速度会比单线程更慢。

2、说说怎么保证线程安全

得分点: 原子类、volatile、锁

线程安全问题是指在多线程背景下,线程没有按照我们的预期执行,导致操作共享变量出现异常。在Java中有许多同步方案提供给我们使用,从轻到重有三种方式:原子类、volatile关键字、锁。

原子类是juc atomic包下的一系列类,通过CAS比较与交换的机制实现线程安全的更新共享变量。通过预期值与内存值的比较来判断是否修改。

volatile关键字是轻量级的同步机制,他实现了变量的可见性、防止指令重排序。保证了【单个变量】读写的线程安全。可见性问题是JMM内存模型中定义每个核心存在一个内存副本导致的,核心只操作他们的内存副本,volatile保证了一旦修改变量则立即刷新到共享内存中,且其他核心的内存副本失效,需要重新读取。

原子类和volatile只能保证单个共享变量的线程安全,锁则可以保证临界区内的多个共享变量线程安全。java中常用的锁有两种:synchronized+juc包下的lock锁。synchronized锁是互斥锁,可以作用于实例方法、静态方法、代码块,基于对象头和Monitor对象,在1.6之后引入轻量级锁、偏向锁等优化。lock锁接口可以通过lock、unlock方法锁住一段代码,基于AQS实现,其加锁解锁就是操作AQS的state变量,并且将阻塞队列存在AQS的双向队列中。除了锁以外,juc包下还提供了一些线程同步工具类,如CountDownLatch、Semaphore等等,我们还可以使用ThreadLocal定义线程局部变量!

3、请说说你对反射的了解

得分点:反射概念,通过反射机制可以实现什么

反射就是在程序运行期间动态的获取对象的属性和方法的功能叫做反射。它能够在程序运行期间,对于任意一个类,都能知道它所有的方法和属性,对于任意一个对象,都能知道他的属性和方法。 获取Class对象的三种方式:getClass();xx.class;Class.forName("xxx"); 反射的优缺点: 优点:运行期间能够动态的获取类,提高代码的灵活性。 缺点:性能比直接的Java代码要慢很多。

常见的应用场景有: - 使用JDBC时,如果要创建数据库的连接,则需要先通过反射机制加载数据库的驱动程序; - 多数框架都支持注解/XML配置,从配置中解析出来的类是字符串,需要利用反射机制实例化; - 面向切面编程(AOP)的实现方案,是在程序运行时创建目标对象的代理类,这必须由反射机制来实现。

4、请你说说ArrayList和LinkedList的区别

得分点: 数据结构、访问效率

(1)、ArrayList的实现是基于数组,LinkedList的实现是基于双向链表。

(2)、对于随机访问ArrayList要优于LinkedList,ArrayList可以根据下标以O(1)时间复杂度对元素进行随机访问,而LinkedList的每一个元素都依靠地址指针和它后一个元素连接在一起,查找某个元素的时间复杂度是O(N)

(3)、 对于插入和删除操作,LinkedList要优于ArrayList,因为当元素被添加到LinkedList任意位置的时候,不需要像ArrayList那样重新计算大小或者是更新索引。

(4)、 LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。

5、你知道哪些线程安全的集合?

得分点: Collections、java.util.concurrent (JUC)

java.util包下的集合类中,大部分都是非线程安全的,但也有少数的线程安全的集合类,例如Vector、Hashtable,它们都是非常古老的API。虽然它们是线程安全的,但是性能很差,已经不推荐使用了。

对于这个包下非线程安全的集合,可以利用Collections工具类,该工具类提供的synchronizedXxx()方法,可以将这些集合类包装成线程安全的集合类。

从JDK 1.5开始,并发包下新增了大量高效的并发的容器,这些容器按照实现机制可以分为三类。第一类是以降低锁粒度来提高并发性能的容器,它们的类名以Concurrent开头,如ConcurrentHashMap。第二类是采用写时复制技术实现的并发容器,它们的类名以CopyOnWrite开头,如CopyOnWriteArrayList。第三类是采用Lock实现的阻塞队列,内部创建两个Condition分别用于生产者和消费者的等待,这些类都实现了BlockingQueue接口,如ArrayBlockingQueue。

加分回答 Collections还提供了如下三类方法来返回一个不可变的集合,这三类方法的参数是原有的集合对象,返回值是该集合的“只读”版本。通过Collections提供的三类方法,可以生成“只读”的Collection或Map。 emptyXxx():返回一个空的不可变的集合对象 singletonXxx():返回一个只包含指定对象的不可变的集合对象 unmodifiableXxx():返回指定集合对象的不可变视图

6、请你说说MySQL索引,以及它们的好处和坏处

得分点: 检索效率、存储资源、索引维护

索引就像指向表行的指针,是一种允许查询操作快速确定哪些行符合WHERE子句中的条件,并检索到这些行的其他列值的数据结构;

索引主要有普通索引、唯一索引、主键索引、外键索引、全文索引、复合索引几种;

在大数据量的查询中,合理使用索引的优点非常明显,不仅能大幅提高匹配where条件的检索效率,还能用于排序和分组操作的加速。

索引如果使用不当也有比较大的坏处:比如索引必定会增加存储资源的消耗;同时也增大了插入、更新和删除操作的维护成本,因为每个增删改操作后相应列的索引都必须被更新。

加分回答 只要创建了索引,就一定会走索引吗? 不一定。 比如,在使用组合索引的时候,如果没有遵从“最左前缀”的原则进行搜索,则索引是不起作用的。 举例,假设在id、name、age字段上已经成功建立了一个名为MultiIdx的组合索引。索引行中按id、name、age的顺序存放,索引可以搜索id、(id,name)、(id, name, age)字段组合。如果列不构成索引最左面的前缀,那么MySQL不能使用局部索引,如(age)或者(name,age)组合则不能使用该索引查询。


MySQL索引是一种帮助快速查找数据的数据结构,可以把它理解为书的目录,通过索引能够快速找到数据所在位置。

场景的索引数据结构有:Hash表(通过hash算法快速定位数据,但不适合范围查询,因为需要每个key都进行一次hash)、二叉树(查找和修改效率都比较高),但是在InnoDB引擎中使用的索引是B+Tree,相较于二叉树,B+Tree这种多叉树,更加矮宽,更适合存储在磁盘中。

使用索引增加了数据查找的效率,但是相对的由于索引也需要存储到磁盘,所以增加了存储的压力,并且新增数据时需要同步维护索引。但是合理的使用索引能够极大提高我们的效率!

7、请你说一下抽象类和接口的区别

得分点: 接口与抽象类的方法,接口与抽象类的常量与变量,单继承多实现

1.抽象类多用于在同类事物中有无法具体描述的方法的场景,而接口多用于不同类之间,定义不同类之间的通信规则。

2.接口只有定义,而抽象类可以有定义和实现。

3.接口需要实现implement,抽象类只能被继承extends,一个类可以实现多个接口,但一个类只能继承一个抽象类。

4.抽象类倾向于充当公共类的角色,当功能需要累积时,用抽象类;接口被运用于实现比较常用的功能,功能不需要累积时,用接口。

8、请你说说Java的特点和优点,为什么要选择Java?

得分点: Java与C++的区别,Java的优点

Java与C++的区别:

Java 是纯粹的面向对象语言,所有的对象都继承自 java.lang.Object,C++ 兼容 C ,不但支持面向对象也支持面向过程。

Java 通过虚拟机从而实现跨平台特性, C++ 依赖于特定的平台。

Java 没有指针,它的引用可以理解为安全指针,而 C++ 具有和 C 一样的指针。

Java 支持自动垃圾回收,而 C++ 需要手动回收。

Java 不支持多重继承,只能通过实现多个接口来达到相同目的,而 C++ 支持多重继承。


1.java语言的特点是:一次编译,到处运行,即平台无关性;是纯面向对象的语言。

2.JAVA语言的优点有:内置的类库简化了开发人员的设计工作;具有较好的安全性和健壮性;开发人员不需要对内存的使用进行管理。

3.选择JAVA的原因是:使用范围很广,安卓操作系统的应用软件目前大部分还是使用JAVA语言编写。

9、请你说说Java基本数据类型和引用类型

得分点: Java中数据类型分类、八大数据类型

Java的数据类型分为基本数据类型和引用数据类型两大类。 基本数据类型共有八大类,这八大数据类型又可分为四小类,分别是整数类型(byte/short/int/long)、浮点类型(float、double)、字符类型(char)和布尔类型(boolean)。其中,int是最常用的整数类型,double是最为常用的浮点类型,除了布尔类型之外的其他7个类型,都可以看做是数字类型,它们相互之间可以进行类型转换。

byte(8), short(16), int(32), long(64), float(32), double(64), char(16), boolean:

byte:1字节(8位),数据范围是 -2^7 ~ 2^7-1。 - short:2字节(16位),数据范围是 -2^15 ~ 2^15-1。 - int:4字节(32位),数据范围是 -2^31 ~ 2^31-1。 - long:8字节(64位),数据范围是 -2^63 ~ 2^63-1。 - float:4字节(32位),数据范围大约是 -3.4*10^38 ~ 3.4*10^38。 - double:8字节(64位),数据范围大约是 -1.8*10^308 ~ 1.8*10^308。 - char:2字节(16位),数据范围是 \u0000 ~ \uffff。 - boolean:Java规范没有明确的规定,不同的JVM有不同的实现机制。

这些基本数据类型有对应的封装类;这基本数据类型在声明之后就会立刻在栈上被分配内存空间。

引用类型包括数组、类、接口类型,还有一种特殊的null类型,所谓引用数据类型就是对一个对象的引用,对象包括实例和数组两种。这些变量在声明时不会被分配内存空间,只是存储了一个内存地址。

10、请你说一下final关键字

得分点: final类,final方法,final变量

final可以修饰类,方法,变量。 final修饰类,该类不可被继承。 final修饰方法,该方法不能被重写。 final修饰变量,如果是基本变量则值不能再改变,如果是引用变量则引用地址不能改变,但值可以改变。