您的位置:首页 > 编程语言 > Java开发

java小知识点

2016-12-28 18:22 204 查看
1、内存泄漏:memory leak

指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏可能会导致内存溢出。

2、wait方法属于object类,而非Thread

wait是object类的方法,只能在同步控制块或者同步控制方法中使用

3、静态方法和属性,所有对象共用一份。

4、位运算

 &:11为1,其他为0

|:00为0 ,其他为1

 ^ :0^0 = 0, 1^0 = 1,  0^1 = 1,  1^1 = 0



 

5、解释

static String str0="0123456789";

static String str1="0123456789";

String str2=str1.substring(5);

String str3=new String(str2);

String str4=new String(str3.toCharArray());

str0=null;

假定str0,...,str4后序代码都是只读引用。

Java 7中,以上述代码为基础,在发生过一次FullGC后,上述代码在Heap空间(不包括PermGen)保留的字符数为(15)

解释:这是一个关于java的垃圾回收机制的题目。垃圾回收主要针对的是堆区的回收,因为栈区的内存是随着线程而释放的。堆区分为三个区:年轻代(Young

 Generation)、年老代(OldGeneration)、永久代(Permanent  Generation,也就是方法区)。

  年轻代:对象被创建时(new)的对象通常被放在Young(除了一些占据内存比较大的对象),经过一定的Minor

  GC(针对年轻代的内存回收)还活着的对象会被移动到年老代(一些具体的移动细节省略)。

  年老代:就是上述年轻代移动过来的和一些比较大的对象。Minor  GC(FullGC)是针对年老代的回收

  永久代:存储的是final常量,static变量,常量池。

  str3,str4都是直接new的对象,而substring的源代码其实也是new一个string对象返回,

  经过fullgc之后,年老区的内存回收,则年轻区的占了15个,不算PermGen。

 方法区:主要存储结构信息的地方,比如方法体,同时也是存储静态变量,以及静态代码块的区域,构造函数,常量池,接口初始化等等

 方法区物理上还是在堆中,是在堆的持久代里面。堆有年轻代

  (由一个Eden区和俩个survivor区组成),老年代,持久代。新创建的对象都在年轻代的Eden区,经过一次JC收集后,存活下来的会被复制到survivor区(一个满了,就全部移动到另外一个大的中,但要保证其中一个survivor为空),经过多次JC后,还存活的对象就被移到老年代了。

  持久代就是经常说的方法区里面存放类信息,常量池,方法等 static String str0="0123456789"; static String str1="0123456789";是放在方法区里。也就是持久代,题目中已经说了,不包含持久代,所以剩余空间为5+5+5=15.

 

 6、概念

如果子类是非抽象类,则必须实现接口中的所有方法; 
如果子类是抽象类,则可以不实现接口中的所有方法,因为抽象类中允许有抽象方法的存在!
 

7、final:修饰符(关键字)有三种用法:

如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和 abstract是反义词。

将变量声明为final,可以保证它们在使用中不被改变,被声明为final 的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。

被声明为final 的方法也同样只能使用,不能在子类中被重写。

8、finally解释

通常放在try…catch的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。

9、finalize:

Object类中定义的方法,Java 中允许使用finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize() 方法可以整理系统资源或者执行其他清理工作。

10、数据库设计

    1.经常用于查询的字段,可作为索引,减少访问的数据量

    2.唯一性太差的字段不选择作为索引(如,状态等只有几个值的情况下),即使经常用于查询

    3.更新非常频繁的字段不适合创建索引,因为更新数据的同时,还要更新索引数据,造成更大的io

    4.不会出现在 WHERE 子句中的字段不该创建索引

 

11、并发问题

高并发、任务执行时间短的业务怎样使用线程池?并发不高、任务执行时间长的业务怎样使用线程池?并发高、业务执行时间长的业务怎样使用线程池? 

(1)高并发、任务执行时间短的业务,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换

(2)并发不高、任务执行时间长的业务要区分开看:

      a)假如是业务时间长集中在IO操作上,也就是IO密集型的任务,因为IO操作并不占用CPU,所以不要让所有的CPU闲下来,

           可以加大线程池中的线程数目,让CPU处理更多的业务

      b)假如是业务时间长集中在计算操作上,也就是计算密集型任务,这个就没办法了,和(1)一样吧,线程池中的线程数设置得少一些,减少线程上下文的切换

(3)并发高、业务执行时间长,解决这种类型任务的关键不在于线程池而在于整体架构的设计,看看这些业务里面某些数据是否能做缓存是第一步,增加服务器是第二步,至于线程池的设置,设置参考(2)。最后,业务执行时间长的问题,也可能需要分析一下,看看能不能使用中间件对任务进行拆分和解耦。

12、单例模式

public class Singleton {
private static Singleton singleton;
private static Lock lock = new ReentrantLock();
private Singleton(){};
public static Singleton getInstance(){
if(singleton == null){
lock.lock();
try {
if(singleton == null){
singleton = new Singleton();
}
} finally{
lock.unlock();
}
}
return singleton;
}
}
基本概念:分饿汉,懒汉模式。实现:只提供私有构造函数 与 getInstance 方法。

普通的单例模式的实现不支持多线程环境,若需支持则要结合 synchronized 或者 lock 等多线程处理方式。
synchronized是托管给JVM执行的,而lock是Java写的控制锁的代码。在Java1.5中,synchronize是性能低效的。因为这是一个重量级操作,需要调用操作接口,导致有可能加锁消耗的系统时间比加锁以外的操作还多。相比之下使用Java提供的Lock对象,性能更高一些。但是到了Java1.6,发生了变化。synchronize在语义上很清晰,可以进行很多优化,有适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在Java1.6上synchronize的性能并不比Lock差。官方也表示,他们也更支持synchronize,在未来的版本中还有优化余地。说到这里,还是想提一下这2中机制的具体区别。据我所知,synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。而Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare
and Swap)。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。

13、集合

Java 集合主要分为两个派系,一个是 Collection 系列,一个是 Map 系列。

Collection:根接口,没有实现类。

List:插入的值允许为空,也允许有重复的值。

ArrayList:数组的实现方式。不同步。

Vector:也是数组的实现方式。同步。(相当于ArrayList的一个同步版本)

LinkedList:真正的链表实现方式。不同步。

比较重要的 Map 有 HashMap,LinkedHashMap,TreeMap,HashTable,还有一个没写出来就是 ConcurenHashMap。那么对于他们的一些特点,简略概括起来就是:

HashMap:发生哈希冲突的Node会加入到链表的最下端;哈希冲突过多的情况下链表会变成红黑树从而保证效率;非同步,不保证顺序。允许有空值和空键。

LinkedHashMap:继承HashMap,Iterator下能保证插入的先后顺序,原理是在LinkedHashMap中加入了链表,并且该链表还是一个双向链表。

TreeMap:能够根据 key 值来有序插入,原理使用了红黑树,每次插入都会对树进行调整。

HashTable:HashMap的线程安全版本,内部的实现几乎和 HashMap 一模一样。但是由于其同步是使用了 synchronized,效率较低。

ConcurrentHashMap:也是HashMap的线程安全版本,并且使用了分段加锁机制,所以效率上要比HashTable要好很多。

那么对于每一个类(接口)的细节,可以看:

Java 集合:HashMap(put方法的实现 与 哈希冲突)

Java 集合:LinkedHashMap(特点,Demo以及实现原理)

Java 集合:TreeMap(特点,Demo以及实现原理)

Java 集合:HashSet,HashTable,以及 ConcurrentHashMap 概念
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java