目录
18.说一下 runnable和 callable有什么区别?
21.final 和 finally ,finalize的区别?
27.Java 关键字 volatile 与 synchronized 作用与区别?
38.Sleep()、suspend()和 wait()之间有什么区别?
39.String,StringBuilder和StringBuffer的区别?
48.什么是 Java Timer 类?如何创建一个有特定时间间隔的任务?
54.有三个线程 T1,T2,T3,怎么确保它们按顺序执行?
65.java中break,continue,return 的区别?
68.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
71.抽象类(abstract class)和接口(interface)有什么异同?
73.抽象的(abstract)方法是否可同时是静态的(static), 是否可同时是本地方法(native),是否可同时被 synchronized?
78.什么是 java 序列化,如何实现 java 序列化?
81.Java中的变量,代码块,构造器之间执行的顺序是怎样的?
82.throws,throw,try,catch,finally分别代表什么意?
1.java的基本数据类型有哪些?
-
1.byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。
-
2.short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。
-
3.int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。
-
4.long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。
-
5.float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
-
6.double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
-
7.boolean:只有true和false两个取值。
-
8.char:16位,存储Unicode码,用单引号赋值。
2.int和Integer的区别?
-
Int 是基本数据类型呀 Integer 是 java 为 int 提供的封装类,是引用数据类型; Int 的默认值为 0,而 integer 的默认值为 null
3.什么是重载和重写?
-
重写就是父类与子类之间的多态
-
重载是在一个类中多态对的体现
-
(1)方法重载是一个类中 定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方 法的重载(Overloading)。
-
(2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返 回值也一样的方法,就称为重写(Overriding)。
4.==和equals的区别?
-
"=="比较的是两个字符串的内存地址。 "equals"比较的是两个字符串的实际值。 == 对于简单类型是值比较,对于对象类型是地址比较 equals 是方法,通常是比较两个对象的 hashCode,对于字符串,hashCode 是通过字符串的 内容算出来的,所以间接可以比较两个的内容
5.java中final关键字有哪些作用?
-
其实 Final 是一个安全修饰符,就是用 final 修饰的类不能被继承,用 final 声明的方法不能被重 写,使用 final 声明的变量就相当于常量,不能被修改。
6.HashMap和Hashtable的区别?
-
1.这两个都是是 Map 接口下的实现类,我们开发的时候经常用的是 HashMap 虽然 HashMap 不是线程安全的但是他的存储效率比较高,Hashtable 是线程安全我们看过他底层的 put 方法前面加的 synchronized关键字,但是他的效率太低,我们开发很少用。
-
2.为什么说 hashTable 是线程安全的? 因为看源码的时候里面的 put 方法前面加了 synchronized 关键字。
-
3.什么情况下用 hashMap? 我们有时候在自定义返回 json 字符串的时候,封装到 List 中进行返回。
7.创建线程的方式?
-
1.继承Thread类创建线bai程子类
-
1.在这子类中重写run方法,在run方法内写线程任务代码
-
2.创建该子类实例,即是创建了一个线程实例
-
3.调用该实例的start方法来启动该线程
-
-
2.建一个类去实现Runnable接口
-
1.该类去实现接口的run方法,run方法内写线程任务代码
-
2.创建该类实例,把该实例当作一个标记target传给Thread类,如:Thread t = new Thread(该类实例);即创建一个线程对象
-
3.调用线程的star方法来启用该线程
-
-
3.最后一种就是实现 Callable 接口
8.什么是浅拷贝与深拷贝?
-
简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
9.深拷贝与浅拷贝的区别?
-
1.浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
-
2.深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。
-
3.浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
-
4.深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。
10.面向对象有哪些特征?
-
1、封装:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面;面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
-
2、继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法;对象的一个新类可以从西现有的类中派生,这个过程称为新类的基类(也就是父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更合适特殊的需要。
-
3、多态性:多态性是指允许不用类的对象对同一消息做出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很多的解决了应用程序函数同名问题。
11.什么是死锁?怎么防止死锁?
-
1.线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。当线程进入对象的synchronized代码块时,便占有了资源,直到它退出该代码块或者调用wait方法,才释放资源,在此期间,其他线程将不能进入该代码块。当线程互相持有对方所需要的资源时,会互相等待对方释放资源,如果线程都不主动释放所占有的资源,将产生死锁。
-
2.从根部解决(从产生死锁的原因入手)
-
1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
-
2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
-
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
-
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
-
-
3.有序资源分配法
-
4.银行家算法
13.swtich选择语句中支持哪些数据类型?
-
在JDK1.5之前,switch循环只支持byte short char int,枚举五种数据类型.
-
jdk1.7开始支持String类型
14.什么是泛型?
-
我记得泛型是 JDK1.5 以后有的,我觉得使用泛型的好处就是让我们的集合变的 更安全一些,省去了强制转换
15.堆栈的区别?
-
1.堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。
-
2.栈内存用来存储局部变量和方法调用。
-
3.栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。
-
4.堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。
16.什么是线程同步,异步?
-
1.线程同步:是多个线程同时访问同一资源,等待资源访问结束,浪费时间,效率不高
-
2.线程异步:访问资源时,如果有空闲时间,则可在空闲等待同时访问其他资源,实现多线程机制
17.乐观锁和悲观锁的区别?
-
对于乐观锁和悲观锁的区别及应用,要牢记一句话:读取频繁使用乐观锁,写入频繁使用悲观锁
-
1.乐观锁假定不会发生冲突,只有在提交操作的时候检查是否有冲突
-
2.悲观锁假定会发生冲突,访问的时候都要先获得锁,保证同一个时刻只有线程获得锁,读读也会阻塞
18.说一下 runnable和 callable有什么区别?
-
1.Runnable 接口 run 方法无返回值;Callable 接口 call 方法有返回值,支持泛型
-
2.Runnable 接口 run 方法只能抛出运行时异常,且无法捕获处理;Callable 接口 call 方法允许抛出异常,可以获取异常信息
19.接口和类有什么区别和相同点?
-
1.不同点:
-
接口不能直接实例化。
-
接口不包含方法的实现。
-
接口可以多继承,类只能单继承。
-
类定义可以在不同的源文件之间进行拆分。
-
-
2.相同点:
-
接口、类和结构都可以从多个接口继承。
-
接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
-
接口和类都可以包含事件、索引器、属性。
-
20.线程的run()和start()有什么区别?
-
1.调用 start() 方法是用来启动线程的,轮到该线程执行时,会自动调用 run();直接调用 run() 方法,无法达到启动多线程的目的,相当于主线程线性执行 Thread 对象的 run() 方法。
-
2.一个线程对应的 start() 方法只能调用一次,多次调用会抛出 java.lang.IllegalThreadStateException 异常;run() 方法没有限制。
21.final 和 finally ,finalize的区别?
-
1.final修饰符(关dao键字)如果一个类dao被声明为final,意版味着它不能再派生出新的子类,权不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。
-
2.finally再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。
-
3.finalize方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。
22.ArrayList 与 LinkedList 区别?
-
1.ArrayList 使用数组方式存储数据,所以根据索引查询数据速度快,而新增或者 删除元素时需要设计到位移操作,所以比较慢。
-
2.LinkedList 使用双向链接方式存储数据,每个元素都记录前后元素的指针, 所以插入、删除数据时只是更改前后元素的指针指向即可,速度非常快,然后通过下标查询元素时需要从头开始索引,所以比较慢,但是如果查询前几个元素或 后几个元素速度比较快。
23.静态变量与非静态变量的区别?
-
1.java在类加载的过程中,再把.class文件加载进内存的时候就为静态变量在运行时数据区的方法区中分配内存,而且只分配一次.
-
2.非static变量每创建一个实例的时候就会在堆中被分配一次内存,每个实例都有一个独立的非static变量
-
3.简而言之,static变量属于整个类,而不属于任何一个实例,生命周期取决于类.非static变量,属于实例,生命周期跟着实例走
24.什么是内存溢出,内存泄漏?
-
1.内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
-
2.内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memory leak会最终会导致out of memory!
25.Throw 和 Throws 的区别?
-
throw 是抛出自定义异常的,throws 是在方法上抛出异常的.
26.JDK7 和 JDK8 区别?
-
我了解JDK8的新特性有:就是接口里也可添加普通的方法了,不用非得是抽象方法了, 但是必须得用default进行修饰,调用的时候也还是得实现这个接口以后才能调用,还有就 是添加了一个Lambda 表达式,让我们遍历集合数据的时候速度更快,我大概就知道这些, 我们目前开发也还没用到过这些新特性,对了,还有就是JDK1.8以后的map存储方式是1.7 的也有些区别.如果不相等则形成链表结构,jdk1.7后加的在前面,先加的移下,这种情 况叫碰撞。这种碰撞的情况应尽量避免,否存一个索引中链表的数据大量时,该索引当再 次插入一个对象时equals比较全部影响效率。 因此jdk1.8改善这种碰撞情况的出现,jdk1.8中的HashMap存储结构是由数组、链表、 红黑树这三种数据结构形成,红黑树查询删除快新增慢。
27.Java 关键字 volatile 与 synchronized 作用与区别?
-
1.volatile
-
它所修饰的变量不保留拷贝,直接访问主内存中的。在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器)。为了性能,一个线程会在自己的memory中保持要访问的变量的副本。这样就会出现同一个变 量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory中的值,或者main memory中的值不一致的情况。 一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程memory中。
-
-
2.synchronized
-
当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
-
-
区别:
-
一、volatile是变量修饰符,而synchronized则作用于一段代码或方法。
-
二、volatile只是在线程内存和“主”内存间同步某个变量的值;而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。
-
28.解决hashmap线程不安全问题?
-
可以通过 collections 集合工具类对不安全的线程进行包装,使其变成线程安全的,也可以 在使用其时加 synchronized 关键字进行同步
29.Hashmap的底层实现原理
-
这个我在论坛上看过,Hashmap 底层是通过数组和链接联合实现的,当我们创建 hashmap 时 会先创建一个数组,当我们用 put 方法存数据时,先根据 key 的 hashcode 值计算出 hash 值,然后用这个哈希值确定在数组中的位置,再把 value 值放进去,如果这个位置本来没放 东西,就会直接放进去,如果之前就有,就会生成一个链表,把新放入的值放在头部,当用 get 方法取值时,会先根据 key 的 hashcode 值计算出 hash 值,确定位置,再根据 equals 方法从该位置上的链表中取出该 value 值。
30.多线程怎么解决高并发?
-
1.synchronized 关键字主要解决多线程共享数据同步问题。
-
2.ThreadLocal 使用场合主要解决多线程中数据因并发产生不一致问题。
-
3.ThreadLocal 和 Synchonized 都用于解决多线程并发访问但是 ThreadLocal 与 synchronized 有本质的区别:
-
(1)synchronized 是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。
-
(2) ThreadLocal 是为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并 不是同一个对象,这样就隔离了多个线程对数据的数据共享。而 Synchronized 却正好相反, 它用于在多个线程间通信时能够获得数据共享。
-
31.Java中的锁有几种方式
-
两种: Synchronized Lock
-
1.Synchronized的局限性:
-
1.如果这个获取锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但 是又没有释放锁,其他线程便只能干巴巴地等待。(不能主动释放锁)
-
2.当有多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作会发生冲突 现象,但是读操作和读操作不会发生冲突现象如果多个线程都只是进行读操作,所以当一个 线程在进行读操作时,其他线程只能等待无法进行读操作。(不分情况,一律锁死)
-
-
2.Lock 的几个实现类 ReentrantLock是一个可重入的互斥锁,又被称为“独占锁” ReadWriteLock,顾名思义,是读写锁。它维护了一对相关的锁 — — “读取锁”和“写入 锁”,一个用于读取操作,另一个用于写入操作。他的两个实现类读锁readerLock和写锁 writerLock。
-
32.解释下内存中的栈、堆、方法区的用法?
-
我原来学java的时候知道JVM内存结构主要有三大块:堆内存、方法区和栈。
-
1.堆内存是JVM 中最大的一块内存地址,它主要由年轻代和老年代还有持久代组成,所有new出来的对象都存 储在该区域。
-
2.栈就是暂存数据的地方,每个线程包含一个栈区,栈存放在一级缓存中,存取 速度较快,栈中只保存基础数据类型的对象和自定义对象的引用.每个栈中的数据都是私有 的,其他栈不能访问。
-
3.方法区存放了要加载的类的信息(如类名、修饰符等)、静态变量、 构造函数、final定义的常量、类中的字段和方法等信息
-
33.IO和NIO的区别?
-
这个NIO是jdk1.7以后有的,他们两的主要区别是:io是面向流是阻塞io,nio是面向缓冲,非阻塞的io;io的话每次从流中读取一个或多个字节,知道读取完所有的字节,没有缓存到任何地方。nio读取的是数据是有缓存的,就是说他读取的数据是在缓冲里读的。另外的话,java中的各种io是阻塞的。就是说一个线程调用read或者write()时,这个线程就已经被阻塞了,知道读取到一些数据为止,或者是完全写入。在这个过程中不能干其他的事情,nio的非阻塞模式,当发送一个读取数据的请求的时候,如果它有读取到可用的数据,就什么也不会获取,且不会让线程阻塞写也是这样。非阻塞的io的空闲时间可以用来做其他的操作,所以一个单独二非阻塞线程可以管理多个输入和输出通道,另外nio还有一个selectr(选择器),他是可以管理多个输入输出的通道。我大概了解的也就是这样
34." " 和 null的区别?
-
1.null是没有地址
-
2." "是有地址但是里面的内容是空的
35.线程的状态?
-
1.其实线程一般具有五种状态,即创建(新建态)、就绪、运行、阻塞、终止
36.java的多态表现在哪里?
-
1.编译多态:主要是体现在重载吧,系统在编译时就能确定调度用重载函数的哪个版本。
-
2.运行时多态:主要体现在代码设计的继承性上,子类的对象也是父类的对象,即上溯造型,所以子类对象可以作为父类对象使用,父类的对象变量可以指向子类对象。因此通过一个父类发出的方法调用可能执行的是方法在父类中的实现,也可能是某个子类中的实现,它是由运行时刻具体的对象类型决定的。
37.你对线程优先级的理解是什么?
-
每一个线程都是有优先级的,一般来说,高优先级du的线程在运行时会具有优先权,但这依赖于线程调度的实现,这个实现是和操作系统相关的(OSdependent)。可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个int变量(从1-10),1代表最低优先级,10代表最高优先级。
38.Sleep()、suspend()和 wait()之间有什么区别?
-
1.Thread.sleep()使当前线程在指定的时间处于“非运行”(Not Runnable)状态。线程一直持有对象的监视器。比如一个线程当前在一个同步块或同步方法中,其它线程不能进入该块或方法中。如果另一线程调用了interrupt()方法,它将唤醒那个“睡眠的”线程。
-
2.sleep()是一个静态方法。这意味着只对当前线程有效,一个常见的错误是调用t.sleep(),(这里的t是一个不同于当前线程的线程)。即便是执行t.sleep(),也是当前线程进入睡眠,而不是t线程。t.suspend()是过时的方法,使用suspend()导致线程进入停滞状态,该线程会一直持有对象的监视器,suspend()容易引起死锁问题。
-
3.object.wait()使当前线程出于“不可运行”状态,和sleep()不同的是wait是object的方法而不是thread。
39.String,StringBuilder和StringBuffer的区别?
-
1.String是只读字符串,所引用的字符串不能被改变
-
2.Stringbuffer和Stringbuilder定义的可以通过各种方法来达到简单的增删改;
-
3.String和Stringbuilder在单线程环境下使用;
-
4.StringBuffer在多线程环境下使用,可以保证线程同步;
-
5.Stringbuilder 和StringBuffer 实现方法类似,均表示可变字符序列,不过StringBuffer 用synchronized关键字修饰(保证线程同步)
-
运行速度:Stringbuilder最快,StringBuffer次之;String最慢,因为每次都要重新开辟内存,产生很多匿名对象,影响系统性能。
40.什么是线程??
-
线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中.是进程中 的实际运作单位。程序员可以通过它进行多处理器编程.你可以使用多线程对运算 密集型任务提速。比如.如果一个线程完成一个任务要 100 毫秒.那么用十个线程完 成改任务只需 10 毫秒。
41.线程和进程有什么区别?
-
线程是进程的子集.一个进程可以有很多线程.每条线程并行执行不同的任务。 不同的进程使用不同的内存空间.而所有的线程共享一片相同的内存空间。每个线 程都拥有单独的栈内存用来存储本地数据。
42.有哪些不同的线程生命周期?
-
当我们在 Java 程序中新建一个线程时.它的状态是 New。当我们调用线程的 start()方法时.状态被改变为 Runnable。线程调度器会为 Runnable 线程池中的线 程分配 CPU 时间并且讲它们的状态改变为 Running。其他的线程状态还有 Waiting.Blocked 和 Dead。
43.什么是死锁(Deadlock)?如何分析和避免死锁?
-
死锁是指两个以上的线程永远阻塞的情况.这种情况产生至少需要两个以上的 线程和两个以上的资源。 分析死锁.我们需要查看 Java 应用程序的线程转储。我们需要找出那些状态 为 BLOCKED 的线程和他们等待的资源。每个资源都有一个唯一的 id.用这个 id 我 们可以找出哪些线程已经拥有了它的对象锁。 避免嵌套锁.只在需要的地方使用锁和避免无限期等待是避免死锁的通常办法。
44. 什么是线程安全?Vector 是一个线程安全类吗?
-
如果你的代码所在的进程中有多个线程在同时运行.而这些线程可能会同时运 行这段代码。如果每次运行结果和单线程运行的结果是一样的.而且其他的变量的 值也和预期的是一样的.就是线程安全的。一个线程安全的计数器类的同一个实例 对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分成 两组.线程安全和非线程安全的。Vector 是用同步方法来实现线程安全的, 而和它 相似的 ArrayList 不是线程安全的。
45.Java 中如何停止一个线程?
-
Java 提供了很丰富的 API 但没有为停止线程提供 API。JDK 1.0 本来有一些 像 stop(), suspend() 和 resume()的控制方法但是由于潜在的死锁威胁因此在后续 的 JDK 版本中他们被弃用了.之后 Java API 的设计者就没有提供一个兼容且线程安 全的方法来停止一个线程。当 run() 或者 call() 方法执行完的时候线程会自动结束, 如果要手动结束一个线程.你可以用 volatile 布尔变量来退出 run()方法的循环或者 是取消任务来中断线程
46.一个线程运行时发生异常会怎样?
-
简单的说,如果异常没有被捕获该线程将会停止执行。 Thread.UncaughtExceptionHandler 是用于处理未捕获异常造成线程突然中断情况的一 个内嵌接口。当一个未捕获异常将造成线程中断的时候 JVM 会使用 Thread.getUncaughtExceptionHandler()来查询线程的 UncaughtExceptionHandler 并 将线程和异常作为参数传递给 handler 的 uncaughtException()方法进行处理。
47.ThreadLocal 可以用来共享数据吗?
-
不可以
-
ThreadLocal 是采用哈希表的方式来为每个线程都提供一个变量的副本ThreadLocal 保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏
48.什么是 Java Timer 类?如何创建一个有特定时间间隔的任务?
-
java.util.Timer 是一个工具类.可以用于安排一个线程在未来的某个特定时间 执行。Timer 类可以用安排一次性任务或者周期任务。 java.util.TimerTask 是一个实现了 Runnable 接口的抽象类.我们需要去继承 这个类来创建我们自己的定时任务并使用 Timer 去安排它的执行。
49.Java 中的同步集合与并发集合有什么区别?
-
1.同步集合与并发集合都为多线程和并发提供了合适的线程安全的集合.不过并 发集合的可扩展性更高。
-
2.在 Java1.5 之前程序员们只有同步集合来用且在多线程并发的时候会导致争 用.阻碍了系统的扩展性。
-
3.Java5 介绍了并发集合像 ConcurrentHashMap.不仅提供线程安全还用锁分 离和 内部分区等现代技术提高了可扩展性。
50.同步方法和同步块.哪个是更好的选择?
-
同步块是更好的选择.因为它不会锁住整个对象(当然你也可以让它锁住整个对象)。同步方法会锁住整个对象.哪怕这个类中有多个不相关联的同步块.这通常 会导致他们停止执行并需要等待获得这个对象上的锁。
51.什么是线程池? 为什么要使用它?
-
1.创建线程要花费昂贵的资源和时间.如果任务来了才创建线程那么响应时间会 变长.而且一个进程能创建的线程数有限。
-
2.为了避免这些问题.在程序启动的时候就创建若干线程来响应处理.它们被称为 线程池.里面的线程叫工作线程。
-
3.从 JDK1.5 开始.Java API 提供了 Executor 框架让你可以创建不同的线程池。 比如单线程池.每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适 合很多生存期短的任务的程序的可扩展线程池)
52.多线程中的忙循环是什么?
-
1.忙循环就是程序员用循环让一个线程等待.不像传统方法 wait(), sleep() 或 yield() 它们都放弃了 CPU 控制.而忙循环不会放弃 CPU.它就是在运行一个空循环。 这么做的目的是为了保留 CPU 缓存。
-
2.在多核系统中.一个等待线程醒来的时候可能会在另一个内核运行.这样会重建 缓存。为了避免重建缓存和减少等待重建的时间就可以使用它了。
53.多线程有几种实现方式?
-
1.多线程有两种实现方法,分别是继承 Thread 类与实现 Runnable 接口
-
2.线程同步的实现方面有五种
-
synchronized
-
一直持有锁,直至执行结束
-
-
wait
-
使一个线程处于等待状态,并且释放所持有的对象的 lock,需捕获异常。
-
-
notify
-
使一个正在运行的线程处于睡眠状态,是一个静态方法,需捕获异常, 不释放锁。
-
-
sleep
-
唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不 能确切的唤醒某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且 不是按优先级。
-
-
suspend
-
唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的 锁,而是让它们竞争
-
-
54.有三个线程 T1,T2,T3,怎么确保它们按顺序执行?
-
在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的 join()方法 在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保 三个线程的顺序你应该先启动最后一个(T3调用 T2,T2调用 T1),这样 T1就会 先完成而 T3最后完成
55.怎么检测一个线程是否拥有锁?
-
在 java.lang.Thread 中有一个方法叫 holdsLock(),它返回 true 如果当且仅当当 前线程拥有某个具体对象的锁
56.如何在两个线程间共享数据?
-
你可以通过共享对象来实现这个目的,或者是使用像阻塞队列这样并发的数据结 构,用 wait 和 notify 方法实现了生产者消费者模型。
57.什么地方用了多线程?
-
下订单这里,我们一般采用多线程下单,但多线程中我们又需要保证用户抢单的公平性,也就是先抢先下单。我们可以这样实现,用户进入秒杀抢单,如果用户符合抢单资格,只需要记录用户抢单数据,存入队列,多线程从队列中进行消费即可,存入队列采用左压,多线程下单采用右取的方式。
58.Excutors 可以产生哪些线程池?
-
Java 里面线程池的顶级接口是 Executor,但是严格意义上讲 Executor 并不是一个 线程池,而只是一个执行线程的工具。真正的线程池接口是 ExecutorService。 ThreadPoolExecutor 是 Executors 类的底层实现。
59.Java 中多线程同步是什么?
-
即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进 行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又 处于等待状态
60.线程之间如何通信?
-
1.多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。通过 一定的手段使各个线程能有效的利用资源。
-
2.通常情况下,一个次级线程要为主线程完成某种特定类型的任务,这就隐含着表 示在主线程和次级线程之间需要建立一个通信的通道。一般情况下,有下面的几种方 法实现这种通信任务:使用全局变量、使用事件对象、使用消息
61.用户线程和守护线程有什么区别?
-
1.所谓守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如 垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部 分。因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有 守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
-
2.用户线程和守护线程两者几乎没有区别,唯一的不同之处就在于虚拟机的离开: 如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。因 为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了
62.如何暂停一条线程?
-
两种方式暂停一条线程,一个是采取 Thread 类的 sleep()方法,一个是在同步代码 中使用 wait()方法.
63.描述一下JVM加载class文件的原理机制?
-
Java中的所有类,都需要由类加载器装载到JVM中才能运行。类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中。在写程序的时候,我们几乎不需要关心类的加载,因为这些都是隐式装载的,除非我们有特殊的用法,像是反射,就需要显式的加载所需要的类。
-
类加载方式,有两种 :
-
1、隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中。
-
2、显式装载, 通过class.forname()等方法,显式加载需要的类Java类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到jvm中,至于其他类,则在需要的时候才加载。这当然就是为了节省内存开销
-
64.java里有什么数据结构?
-
Java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类。
-
数据结构实现类及区别 :
-
1.ArrayList: 元素单个,效率高,多用于查询
-
2.Vector: 元素单个,线程安全,多用于查询
-
3.LinkedList:元素单个,多用于插入和删除
-
4.HashMap: 元素成对,元素可为空
-
5.HashTable: 元素成对,线程安全,元素不可为空
-
65.java中break,continue,return 的区别?
-
1.break默认是跳出最里层的循环,也就是break所在的最近的那层循环
-
2.continue是终止本次循环,继续下次循环
-
3.return 结束当前方法
66.如果hashtable存储null值会怎么样?
-
编译会通过
-
运行时会报空指针异常的错误
67.JVM结构原理、GC工作机制详解?
-
JVM主要包括四个部分:
-
1.类加载器(ClassLoader)
-
在JVM启动时或者在类运行时将需要的class加载到JVM中。
-
-
2.执行引擎
-
负责执行class文件中包含的字节码指令
-
-
3.本地方法接口
-
主要是调用C或C++实现的本地方法及返回结果。
-
-
4.内存区(也叫运行时数据区)
-
是在JVM运行的时候操作所分配的内存区。运行时内存区主要可以划分为5个区域:堆,栈,方法区,程序计数器,本地方法栈
-
-
-
GC工作机制
68.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
-
1.TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。
-
2.TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。
-
3.Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象必须实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。
69.String类可以被继承吗?
-
String类在声明时使用final关键字修饰,被final关键字修饰的类无法被继承。
70.& 和 && 的区别?
-
&运算符是:逻辑与;&&运算符是:短路与。
-
1.&和&&在程序中最终的运算结果是完全一致的,只不过&&存在短路现象,当&&运算符左边的表达式结果为false的时候,右边的表达式不执行,此时就发生了短路现象。如果是&运算符,那么不管左边的表达式是true还是false,右边表达式是一定会执行的。这就是他们俩的本质区别。
-
-
当然,&运算符还可以使用在二进制位运算上,例如按位与操作。
-
71.抽象类(abstract class)和接口(interface)有什么异同?
-
不同点:
-
1.抽象类中可以定义构造器,接口不能;
-
2.抽象类可以有抽象方法和具体方法,接口不能有具体方法;
-
3.接口中的成员全都是 public 的,抽象类中的成员可以使用private、public、protected、默认等修饰;
-
4.抽象类中可以定义成员变量,接口中只能是常量;
-
5.有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法;
-
6.抽象类中可以包含静态方法,接口中不能有静态方法;
-
7.一个类只能继承一个抽象类,一个类可以实现多个接口;
-
-
相同点:
-
1.都不能够实例化;
-
2.可以将抽象类和接口类型作为引用类型;
-
3.一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类;
-
72.char 型变量中能不能存储一个中文汉字,为什么?
-
char 类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char 类型占2个字节(16 比特),所以放一个中文是没问题的。
73.抽象的(abstract)方法是否可同时是静态的(static), 是否可同时是本地方法(native),是否可同时被 synchronized?
-
都不能。
-
1.抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。
-
2.本地方法是由本地代码(如 C++ 代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。
-
3.synchronized 和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。
74.阐述静态变量和实例变量的区别?
-
不管创建多少个对象,静态变量在内存中有且仅有一个;
-
实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。
-
静态变量可以实现让多个对象共享内存。
75.如何将一个 java 对象序列化到文件里?
-
在 java 中能够被序列化的类必须先实现 Serializable 接口,该接口没有任何抽象方法只是起到一个标记作用。
76.字节流和字符流的区别?
-
字节流读取的时候,读到一个字节就返回一个字节;字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在 UTF-8 码表中是 3 个字节)时。先去查指定的编码表,将查到的字符返回。字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。字节流主要是操作 byte 类型数据,以 byte 数组为准,主要操作类就是 OutputStream、InputStream字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组。所以字符流是由 Java 虚拟机将字节转化为 2 个字节的 Unicode 字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点。在程序中一个字符等于两个字节,java 提供了 Reader、Writer 两个专门操作字符流的类。
77.如何实现对象克隆?
-
有两种方式:
-
1.实现 Cloneable 接口并重写 Object 类中的 clone()方法;
-
2.实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
-
78.什么是 java 序列化,如何实现 java 序列化?
-
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。序 列 化 的 实 现 : 将 需 要 被 序 列 化 的 类 实 现 Serializable 接 口 , 该 接 口 没 有 需 要 实 现 的 方 法 , implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象,接着,使用 ObjectOutputStream 对象的 writeObject(Object obj)方法就可以将参数为 obj 的对象写出(即保存其状态),要恢复的话则用输入流。
79.java线程池有几种?
-
一:newCachedThreadPool(缓存线程型池)
-
(1)缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse,如果没有,就建立一个新的线程加入池中;
-
(2)缓存型池子,通常用于执行一些生存周期很短的异步型任务;因此一些面向连接的daemon型server中用得不多;
-
(3)能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。
-
(4)注意,放入CachedThreadPool的线程不必担心其结束,超过TIMEOUT不活动,其会自动被终止
-
-
二:newFixedThreadPool (缓存线程池和上面的差不多)
-
(1)newFixedThreadPool与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程
-
(2)其独特之处:任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子
-
(3)和cacheThreadPool不同,FixedThreadPool没有IDLE机制(可能也有,但既然文档没提,肯定非常长,类似依赖上层的TCP或UDP IDLE机制之类的),所以FixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器
-
(4)从方法的源代码看,cache池和fixed 池调用的是同一个底层池,只不过参数不同
-
fixed池线程数固定,并且是0秒IDLE(无IDLE
-
cache池线程数支持0-Integer.MAX_VALUE(显然完全没考虑主机的资源承受能力),60秒IDLE
-
-
-
三:ScheduledThreadPool(调度型线程池)
-
(1)调度型线程池
-
(2)这个池子里的线程可以按schedule依次delay执行,或周期执行
-
-
四:SingleThreadExecutor(单例线程)
-
(1)单例线程,任意时间池中只能有一个线程
-
2)用的是和cache池和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE)
-
80.接口有什么好处?
-
1.重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。
-
2、简单、规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些业务,而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无法看明白)。
-
3.维护、拓展性:比如你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,然后你就这样定义了这个类。可是在不久将来,你突然发现这个类满足不了你了,然后你又要重新设计这个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起来很麻烦。如果你一开始定义一个接口,把绘制功能放在接口里,然后定义类时实现这个接口,然后你只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。
-
4.安全、严密性:接口是实现软件松耦合的重要手段,它描叙了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多)。
81.Java中的变量,代码块,构造器之间执行的顺序是怎样的?
-
步骤:
-
1、父类静态变量和静态代码块(先声明的先执行);
-
2、子类静态变量和静态代码块(先声明的先执行);
-
3、父类的变量和代码块(先声明的先执行);
-
4、父类的构造函数;
-
5、子类的变量和代码块(先声明的先执行);
-
6、子类的构造函数。
-
82.throws,throw,try,catch,finally分别代表什么意?
-
1.try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
-
2.catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。
-
3.finally – finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
-
4.throw – 用于抛出异常。
-
5.throws – 用在方法签名中,用于声明该方法可能抛出的异常