synchronized是Java中的关键字,是一种同步锁。
无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;
如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是该类所有的对象。
JAVA的垃圾回收机制
1.1引用计数法:
通过引用计数来判断一个对象是否可以被回收。如果一个对象没有任何引用与之关联,则说明该对象基本不太可能在其他地方被使用到,那么这个对象就成为可被回收的对象了。
存在的问题:object1和object2赋值为null,也就是说object1和object2指向的对象已经不可能再被访问,但是由于它们互相引用对方,导致它们的引用计数器都不为0,那么垃圾收集器就永远不会回收它们。
1.2标记-清除 算法:
从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收。
存在的问题:由于直接回收不存活的对象,因此会造成内存碎片。碎片太多可能会导致后续过程中需要为大对象分配空间时无法找到足够的空间而提前触发新的一次垃圾收集动作。
1.3Copying(复制)算法:
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。
存在的问题:对内存空间的使用做出了高昂的代价,因为能够使用的内存缩减到原来的一半。
1.4generation算法:
分代收集算法是目前大部分JVM的垃圾收集器采用的算法。
一般情况下将堆区划分为老年代和新生代。
老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。
所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。
在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。
System.gc()用于调用垃圾收集器,在调用时,垃圾收集器将运行以回收未使用的内存空间。它将尝试释放被丢弃对象占用的内存。
2.1 GC
GC又分为minor GC 和 Full Gc。
Java 堆内存分为新生代和老年代,新生代中又分为1个Eden区域 和两个 Survivor区域。
eden就相当于是使用空间,survivor就相当于是保留空间
Minor GC 的触发条件:大多数情况下,直接在 Eden 区中进行分配。如果 Eden区域没有足够的空间,那么就会发起一次 Minor GC。
对于 Full GC的触发条件:也是如果老年代没有足够空间的话,那么就会进行一次 Full GC。
*Hashtable
1.1什么时候用Hashtable
如果用到了Key,Value类型的数据,就用Hashtable。
1.2usage
Hashtable table = new Hashtable();
table.put("zhangsan", 22);
table.remove("Beijing");
int value = table.get(key);
//Iterator遍历方式1--键值对遍历entrySet()
Iterator> iter = table.entrySet().iterator();
while(iter.hasNext()){
Map.Entry entry = (Map.Entry)iter.next();
String key = entry.getKey();
int value = entry.getValue();
System.out.println("entrySet:"+key+" "+value);
}
//Iterator遍历方式2--key键的遍历
Iterator iterator = table.keySet().iterator();
keySet() //返回值是个只存放key值的Set集合
返回映射所包含的映射关系的Set集合(一个关系就是一个键-值对)
一些基础问题:
1、访问修饰符不写(默认)?
类的成员不写访问修饰时默认为default。
默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。
2、String 是最基本的数据类型吗?
不是。
Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type)和枚举类型(enumeration type),剩下的都是引用类型(reference type)。
3、内存中的栈(stack)、堆(heap)和静态区(static area)的用法?
我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;
而通过new关键字和构造器创建的对象放在堆空间;
程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在静态区中。
String str = new String("hello");
上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而”hello”这个字面量放在静态区。
4、数组有没有length()方法?String有没有length()方法?
答:数组没有length()方法,有length 的属性。String 有length()方法。
5、在Java中,如何跳出当前的多重嵌套循环?
在最外层循环前加一个标记如A,然后用break A;可以跳出多重循环。
6、两个对象值相同(x.equals(y) == true),hashcode应该相同
(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;
(2)如果两个对象的hashCode相同,它们并不一定相同。
如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降
7、arraylist与vector的区别
a、Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
b、 当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小, ArrayList就有利于节约内存空间。
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用
8、Hashtable和HashMap的区别
HashMap是非线程安全的,非synchronized,只是用于单线程环境下,可以接受null
(key为null的键值对永远都放在以table[0]为头结点的链表中)
Hashtable是线程安全的,多个线程可以共享一个Hashtable,也是synchronized,所以在单线程环境下它比HashMap要慢。
JAVA中的同步与异步:
同步:指发送一个请求,需要等待返回,然后才能够发送下一个请求,有个等待过程;
异步:指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。
并行其实是真正的异步,并发伪异步。
9、是否可以继承String类?
String 类是final类,不可以被继承。
10、String和StringBuilder、StringBuffer的区别?
String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。
而StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改。StringBuilder是在单线程环境下使用的,因此它的效率也比StringBuffer要高。
11、char 型变量中能不能存贮一个中文汉字,为什么?
char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode,一个char类型占2个字节
12、抽象类和接口有什么异同?
a、抽象类和接口都不能够实例化。
b、一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。
**如果一个类里有抽象方法,那么这个类只能是抽象类 **
不同:
c、而接口中不能定义构造器而且其中的方法全部都是抽象方法。,抽象类里可以没有抽象方法 **
d、抽象类中的成员可以是private、默认、protected、public的,而接口中的成员全都是public的。**
e、抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是public static 常量。
f、接口可继承接口,并可多继承接口,但类只能单继承。
g、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
实现接口或继承抽象类的子类必须实现接口的所有方法或抽象类的所有抽象方法。
接口中的成员不能有任何实现
13、抽象的(abstract)方法是否可同时是静态的(static)?
不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。
14、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。
15、GC是什么?为什么要有GC?
GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。
要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。
16、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?
一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
17、Java 中的final关键字有哪些用法?
(1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。
18、 如何将字符串转换为基本数据类型?如何将基本数据类型转换为字符串?
调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;
19、Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?
sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持。
wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法才能唤醒等待池中的线程进入等锁池(lock pool)。
20、Static
在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。
21、JAVA字符串的操作
截取字符串:
String sb = "bbbdsajjds";
sb.substring(2, 4);
从索引号2开始到索引4结束(并且不包含索引4截取在内);
StringBuffer的方法:
StringBuffer sb2 = new StringBuffer(s); //String转换为StringBuffer
String s1 = sb2.toString(); //StringBuffer转换为String
sb2.append("aaa")该方法的作用是追加内容到当前StringBuffer对象的末尾
insert(int offset, boolean b)
sb.reverse();
22、日期
如何格式化日期
DateFormate df=DateFormate.getInstance();
df.Format(dat);
如何取得年月日,小时分秒
Date dat=new Date();
dat.getYear(); dat.getMonth(); dat.getDay(); dat.getHours();dat.getSeconds();
23、I/O操作
InputStream/OutputStream 都是父类,都是抽象类。
FileOutputStream/FileInputStream 本地文件
read &&write 方法
24、JAVA多线程
指的是这个程序(一个进程)运行时产生了不止一个线程
启动一个线程的方法:
MyThread my = new MyThread();
my.start();
25、什么样的字段适合做索引
表的主键、外键必须有索引;
经常与其他表进行连接的表,在连接字段上应该建立索引;
经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;
26、JAVA的多态
重写
接口
抽象类和抽象方法
27、同步、异步、阻塞、非阻塞概念
同步、异步:关注的是如何获取结果,直接获取还是等待通知。
阻塞和非阻塞是指进程访问的数据如果尚未就绪,进程是否需要等待
阻塞,就是调用结果返回之前,该执行线程会被挂起,不释放CPU执行权,线程不能做其它事情,只能等待,只有等到调用结果返回了,才能继续;
非阻塞,就是在没有获取调用结果时,不是一直等待,线程可以往下执行
28、线程挂起
线程挂起和恢复方法1:wait()与notify()方法
线程挂起2:sleep()方法
29、java GC是在什么时候,对什么东西,做了什么事情?
对什么东西:从GC Roots搜索不到,而且经过一次标记清理之后仍没有复活的对象。
做什么:
新生代:复制清理;
老年代:标记-清除和标记-压缩算法;
永久代:存放Java中的类和加载类的类加载器本身。
30、讲讲类的实例化顺序,当 new 的时候, 他们的执行顺序。
父类静态代变量、
父类静态代码块、
子类静态变量、
子类静态代码块、
父类非静态变量(父类实例成员变量)、
父类构造函数、
子类非静态变量(子类实例成员变量)、
子类构造函数。
31、LinkedList
LinkedList的本质是双向链表。
LinkedList包含两个重要的成员:header 和 size。
//迭代器遍历
Iterator iterator = linkedList.iterator();
while(iterator.hasNext()){
iterator.next();
}
分配内存空间不是必须是连续的;
插入、删除操作很快,只要修改前后指针就OK了,时间复杂度为O(1);
void add(int index, E element):在指定位置插入一个元素。
32、核心 Map
HashMap
Hashtable
entrySet()返回 Map 中所包含映射的 Set 视图。
Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素
equals(Object o) 比较指定对象与此 Map 的等价性
hashCode() 返回此 Map 的哈希码
33、I/O模型
所有的系统I/O都分为两个阶段:等待就绪和操作。读函数,分为等待系统可读和真正的读;同写函数分为等待网卡可以写和真正的写。
同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。
34、JAVA反射机制提供了什么功能
获取类的Class对象
获取类的Fields
获取类的Method
获取类的Constructor
新建类的实例
35、动态代理
若代理类在程序运行前就已经存在,那么这种代理方式被成为【静态代理】 ,这种情况下的代理类通常都是我们在Java代码中定义的。
代理类:
public interface FontProvider {
Font getFont(String name);
}
public abstract class ProviderFactory {
public static FontProvider getFontProvider() {
return new FontProviderFromDisk();
}
}
现在我们希望给他加上一个缓存功能,我们可以用静态代理来完成
public class CachedFontProvider implements FontProvider {
private FontProvider fontProvider;
private Map cached;
public CachedFontProvider(FontProvider fontProvider) {
this.fontProvider = fontProvider;
}
……
}
/* 对工厂类进行相应修改,代码使用处不必进行任何修改。
这也是面向接口编程以及工厂模式的一个好处 */
public abstract class ProviderFactory {
public static FontProvider getFontProvider() {
return new CachedFontProvider(new FontProviderFromDisk());
}
}
}
动态代理:考虑以下各种情况,有多个提供类,每个类都有getXxx(String name)方法,每个类都要加入缓存功能,使用静态代理虽然也能实现,但是也是略显繁琐,需要手动一一创建代理类。
public class CachedProviderHandler implements InvocationHandler {
private Map cached = new HashMap<>();
private Object target;
public CachedProviderHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
……
}
return method.invoke(target, args);
}
}
public abstract class ProviderFactory {
public static FontProvider getFontProvider() {
Class targetClass = FontProvider.class;
return (FontProvider) Proxy.newProxyInstance(targetClass.getClassLoader(),
new Class[] { targetClass },
new CachedProviderHandler(new FontProviderFromDisk()));
}
}
主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法),因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象,具体应用的话,比如可以添加调用日志,做事务控制等。
36、jvm 中一次完整的 GC 流程是怎样的
对象诞生即新生代->eden,在进行minor gc过程中,如果依旧存活,移动到from,变成Survivor,进行标记代数,如此检查一定次数后,晋升为老年代
37、线程的挂起和唤醒
notify( )方法,唤醒在此对象监视器上等待的单个线程,只会通知等待队列中的第一个相关线程。
wait( )放弃当前对资源的占有权, 导致当前的线程等待,直到其他线程调用此对象的notify( ) 方法或 notifyAll( ) 方法
sleep()方法使线程进入休眠状态,线程在指定时间内不会运行。
join()方法使线程挂起,使自己等待另一个线程的结果,直到另一个线程执行完毕为止。
38、导致线程死锁的原因?怎么解除线程死锁?
- 互斥条件:一个资源每次只能被一个线程使用。
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
只要破坏死锁 4 个必要条件之一中的任何一个,死锁问题就能被解决。
39、简述 Http 请求 get 和 post 的区别以及数据包格式。
get大小有限制,post没有限制
40、聚集索引和非聚集索引的区别。
聚集索引就是索引和记录紧密在一起。
非聚簇索引 索引文件和数据文件分开存放,索引文件的叶子页只保存了主键值,要定位记录还要去查找相应的数据块。
41、ACID 是什么。
atomic,原子性,要么都提交,要么都失败,不能一部分成功,一部分失败。
consistent,一致性,事物开始及结束后,数据的一致性约束没有被破坏
isolation,隔离性,并发事物间相互不影响,互不干扰。
durability,持久性,已经提交的事物对数据库所做的更新必须永久保存。即便发生崩溃,也不能被回滚或数据丢失。
42、