2018-08-02 15:58:10 +08:00
|
|
|
|
<!-- TOC -->
|
2018-07-25 10:37:01 +08:00
|
|
|
|
|
2018-08-02 15:58:10 +08:00
|
|
|
|
- [HashMap ConcurrentHashMap](#hashmap-concurrenthashmap)
|
|
|
|
|
- [java this 和 super的用法](#java-this-和-super的用法)
|
|
|
|
|
- [this](#this)
|
|
|
|
|
- [super](#super)
|
|
|
|
|
- [super和this的异同:](#super和this的异同)
|
|
|
|
|
- [抽象类和接口](#抽象类和接口)
|
|
|
|
|
- [Synchronized 和 volitate区别](#synchronized-和-volitate区别)
|
|
|
|
|
- [异常](#异常)
|
|
|
|
|
- [String StringBuffer StringBuilder的区别](#string-stringbuffer-stringbuilder的区别)
|
|
|
|
|
- [运行速度:](#运行速度)
|
|
|
|
|
- [线程安全](#线程安全)
|
|
|
|
|
- [总结](#总结)
|
|
|
|
|
- [java 如何实现序列化](#java-如何实现序列化)
|
|
|
|
|
- [什么是cookie?Session和cookie有什么区别?](#什么是cookiesession和cookie有什么区别)
|
|
|
|
|
- [如何避免死锁](#如何避免死锁)
|
|
|
|
|
- [进程和线程区别](#进程和线程区别)
|
|
|
|
|
- [参考文档](#参考文档)
|
|
|
|
|
|
|
|
|
|
<!-- /TOC -->
|
|
|
|
|
|
|
|
|
|
# HashMap ConcurrentHashMap
|
2018-07-27 13:33:34 +08:00
|
|
|
|
|
|
|
|
|
HashMap和ConcurrentHashMap的最主要的区别就是前者是线程不安全,后者是线程安全的。在不同的JDK版本中,区别也不一样
|
|
|
|
|
|
|
|
|
|
JDK1.7中:
|
|
|
|
|
|
|
|
|
|
HashMap使用**链表法**来实现hash冲突节点的存储。ConcurrentHashMap使用Segment 数组存储数据,Segment 通过继承 ReentrantLock 来进行加锁。
|
|
|
|
|
|
|
|
|
|
JDK1.8中:
|
|
|
|
|
|
|
|
|
|
HashMap重复hash值的链表元素超过8个,就改成红黑树实现
|
|
|
|
|
|
|
|
|
|
ConcurrentHashMap 不用segment,改成CAS+synchronized方法实现。
|
|
|
|
|
|
|
|
|
|
CAS 的含义是“我认为原有的值应该是什么,如果是,则将原有的值更新为新值,否则不做修改,并告诉我原来的值是多少”
|
|
|
|
|
|
2018-08-02 15:58:10 +08:00
|
|
|
|
# java this 和 super的用法
|
|
|
|
|
|
|
|
|
|
## this
|
|
|
|
|
|
|
|
|
|
this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。
|
|
|
|
|
|
|
|
|
|
this 的用法主要有三种:
|
|
|
|
|
|
|
|
|
|
- 普通的直接引用,this 相当于当前对象本身
|
|
|
|
|
- 形参与成员名字重名,用this来区分
|
|
|
|
|
- 引用构造函数 (**必须放在构造函数的第一行**)
|
|
|
|
|
|
|
|
|
|
``` java
|
|
|
|
|
class Person {
|
|
|
|
|
private int age = 10;
|
|
|
|
|
public Person(){
|
|
|
|
|
System.out.println("初始化年龄:"+age);
|
|
|
|
|
}
|
|
|
|
|
public int GetAge(int age){
|
|
|
|
|
this.age = age;
|
|
|
|
|
return this.age;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## super
|
|
|
|
|
|
|
|
|
|
super 指的是自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。
|
|
|
|
|
|
|
|
|
|
super 也有三种用法:
|
|
|
|
|
|
|
|
|
|
- 普通的直接引用
|
|
|
|
|
- 子类中的成员变量或方法与父类中的成员变量或方法同名
|
|
|
|
|
- 引用构造函数
|
|
|
|
|
|
|
|
|
|
``` java
|
|
|
|
|
class Country {
|
|
|
|
|
String name;
|
|
|
|
|
void value() {
|
|
|
|
|
name = "China";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class City extends Country {
|
|
|
|
|
String name;
|
|
|
|
|
void value() {
|
|
|
|
|
name = "Shanghai";
|
|
|
|
|
super.value(); //调用父类的方法
|
|
|
|
|
System.out.println(name);
|
|
|
|
|
System.out.println(super.name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
City c=new City();
|
|
|
|
|
c.value();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**super 作为引用构造函数的时候,必须放在第一行**
|
|
|
|
|
|
|
|
|
|
``` java
|
|
|
|
|
class Person {
|
|
|
|
|
public static void prt(String s) {
|
|
|
|
|
System.out.println(s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Person() {
|
|
|
|
|
prt("父类·无参数构造方法: "+"A Person.");
|
|
|
|
|
}//构造方法(1)
|
|
|
|
|
|
|
|
|
|
Person(String name) {
|
|
|
|
|
prt("父类·含一个参数的构造方法: "+"A person's name is " + name);
|
|
|
|
|
}//构造方法(2)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class Chinese extends Person {
|
|
|
|
|
Chinese() {
|
|
|
|
|
super(); // 调用父类构造方法(1)
|
|
|
|
|
prt("子类·调用父类”无参数构造方法“: "+"A chinese coder.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Chinese(String name) {
|
|
|
|
|
super(name);// 调用父类具有相同形参的构造方法(2)
|
|
|
|
|
prt("子类·调用父类”含一个参数的构造方法“: "+"his name is " + name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Chinese(String name, int age) {
|
|
|
|
|
this(name);// 调用具有相同形参的构造方法(3)
|
|
|
|
|
prt("子类:调用子类具有相同形参的构造方法:his age is " + age);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
Chinese cn = new Chinese();
|
|
|
|
|
cn = new Chinese("codersai");
|
|
|
|
|
cn = new Chinese("codersai", 18);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## super和this的异同:
|
|
|
|
|
|
|
|
|
|
super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)
|
|
|
|
|
this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
|
|
|
|
|
super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
|
|
|
|
|
this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
|
|
|
|
|
调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
|
|
|
|
|
super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。
|
|
|
|
|
super()和this()均需放在构造方法内第一行。
|
|
|
|
|
尽管可以用this调用一个构造器,但却不能调用两个。
|
|
|
|
|
this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
|
|
|
|
|
this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
|
|
|
|
|
从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 抽象类和接口
|
|
|
|
|
|
|
|
|
|
抽象类与接口:
|
|
|
|
|
|
|
|
|
|
抽象类和抽象方法都使用 abstract 进行声明。抽象类一般会包含抽象方法,抽象方法一定位于抽象类中。
|
|
|
|
|
抽象类和普通类最大的区别是,抽象类不能被实例化,需要继承抽象类才能实例化其子类。
|
|
|
|
|
|
|
|
|
|
接口是抽象类的延伸,在 Java 8 之前,它可以看成是一个完全抽象的类,也就是说它不能有任何的方法实现。
|
|
|
|
|
从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8
|
|
|
|
|
之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类。
|
|
|
|
|
|
|
|
|
|
接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected。
|
|
|
|
|
接口的字段默认都是 static 和 final 的。
|
|
|
|
|
|
|
|
|
|
抽象类和接口的比较
|
|
|
|
|
| | 抽象类 | 接口
|
|
|
|
|
--- | ---| ---
|
|
|
|
|
设计| IS-A, 满足里式替换原则| LIKE-A, 提供一个方法实现契约
|
|
|
|
|
使用| 单继承| 多实现
|
|
|
|
|
字段| 无限制| static or final
|
|
|
|
|
方法| 无限制| public
|
|
|
|
|
|
|
|
|
|
如何使用:
|
|
|
|
|
|
|
|
|
|
使用抽象类:
|
|
|
|
|
|
|
|
|
|
需要在几个相关的类中共享代码。
|
|
|
|
|
需要能控制继承来的方法和域的访问权限,而不是都为 public。
|
|
|
|
|
需要继承非静态(non-static)和非常量(non-final)字段。
|
|
|
|
|
|
|
|
|
|
使用接口:
|
|
|
|
|
|
|
|
|
|
需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Compareable 接口中的 compareTo() 方法;
|
|
|
|
|
需要使用多重继承,例如Runnable接口实现线程类
|
|
|
|
|
|
|
|
|
|
# Synchronized 和 volitate区别
|
|
|
|
|
|
|
|
|
|
[volatile与synchronized的区别](https://www.cnblogs.com/tf-Y/p/5266710.html)
|
|
|
|
|
|
|
|
|
|
1) volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.
|
|
|
|
|
2) volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.
|
|
|
|
|
3) volatile仅能实现变量的修改可见性,而synchronized则可以保证变量的修改可见性和原子性.(**只能保证单个变量的读写原子性,不能保证volatile++这种复合操作的原子性**)
|
|
|
|
|
4) volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.
|
|
|
|
|
5) 当一个域的值依赖于它之前的值时,volatile就无法工作了,如n=n+1,n++等。如果某个域的值受到其他域的值的限制,那么volatile也无法工作,如Range类的lower和upper边界,必须遵循lower<=upper的限制。
|
|
|
|
|
6) 使用volatile而不是synchronized的唯一安全的情况是类中只有一个可变的域。
|
|
|
|
|
|
|
|
|
|
# 异常
|
|
|
|
|
|
|
|
|
|
Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: Error 和 Exception。其中 Error 用来表示 JVM 无法处理的错误,Exception 分为两种:
|
|
|
|
|
|
|
|
|
|
受检异常 :需要用 try...catch... 语句捕获并进行处理,并且可以从异常中恢复;
|
|
|
|
|
非受检异常 :是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序奔溃并且无法恢复。
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
[java入门之异常处理](https://www.tianmaying.com/tutorial/Java-Exception)
|
|
|
|
|
|
|
|
|
|
# String StringBuffer StringBuilder的区别
|
|
|
|
|
|
|
|
|
|
## 运行速度:
|
|
|
|
|
|
|
|
|
|
StingBuilder > StringBuffer > String
|
|
|
|
|
|
|
|
|
|
String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的
|
|
|
|
|
|
|
|
|
|
``` java
|
|
|
|
|
String str = "abc";
|
|
|
|
|
str = str + "de";// 原来的"abc"没了,下次GC会被回收掉,创建了一个新的str变量
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 线程安全
|
|
|
|
|
|
|
|
|
|
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
|
|
|
|
|
|
|
|
|
|
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
|
|
|
|
|
|
|
|
|
|
## 总结
|
|
|
|
|
|
|
|
|
|
String:适用于少量的字符串操作的情况
|
|
|
|
|
|
|
|
|
|
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
|
|
|
|
|
|
|
|
|
|
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# java 如何实现序列化
|
|
|
|
|
|
|
|
|
|
OutputStream.writeObject方法可以实现java对象的序列化,如果想要java自动实现,则需要实现Serializable接口
|
|
|
|
|
|
|
|
|
|
# 什么是cookie?Session和cookie有什么区别?
|
|
|
|
|
|
|
|
|
|
Cookie是会话技术,将用户的信息保存到浏览器的对象.
|
|
|
|
|
|
|
|
|
|
区别:
|
|
|
|
|
|
|
|
|
|
(1)cookie数据存放在客户的浏览器上,session数据放在服务器上
|
|
|
|
|
(2)cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session
|
|
|
|
|
(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE
|
|
|
|
|
(4)单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中
|
|
|
|
|
|
|
|
|
|
# 如何避免死锁
|
|
|
|
|
|
|
|
|
|
死锁的发生必须满足以下四个条件:
|
|
|
|
|
|
|
|
|
|
互斥条件:一个资源每次只能被一个进程使用。
|
|
|
|
|
|
|
|
|
|
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
|
|
|
|
|
|
|
|
|
|
不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
|
|
|
|
|
|
|
|
|
|
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
|
|
|
|
|
|
|
|
|
|
三种用于避免死锁的技术:
|
|
|
|
|
|
|
|
|
|
加锁顺序(线程按照一定的顺序加锁)
|
|
|
|
|
|
|
|
|
|
加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
|
|
|
|
|
|
|
|
|
|
死锁检测
|
|
|
|
|
|
|
|
|
|
(死锁原因及如何避免更深理解移步:http://blog.csdn.net/ls5718/article/details/51896159)
|
|
|
|
|
|
|
|
|
|
# 进程和线程区别
|
|
|
|
|
|
|
|
|
|
**定义:**
|
|
|
|
|
|
|
|
|
|
进程:具有一定的独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立的单位
|
|
|
|
|
|
|
|
|
|
线程:进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
|
|
|
|
|
|
|
|
|
|
- 关系:
|
|
|
|
|
|
|
|
|
|
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
|
|
|
|
|
|
|
|
|
|
相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
|
|
|
|
|
|
|
|
|
|
- 区别:
|
|
|
|
|
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
|
|
|
|
|
|
|
|
|
|
1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
|
|
|
|
|
|
|
|
|
|
2) 线程的划分尺度小于进程,使得多线程程序的并发性高。
|
|
|
|
|
|
|
|
|
|
3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
|
|
|
|
|
|
|
|
|
|
4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
|
|
|
|
|
|
|
|
|
|
5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
|
|
|
|
|
|
|
|
|
|
- 优缺点:
|
|
|
|
|
线程和进程在使用上各有优缺点:
|
|
|
|
|
|
|
|
|
|
线程执行开销小,但不利于资源的管理和保护;
|
|
|
|
|
|
|
|
|
|
而进程正相反。
|
|
|
|
|
|
|
|
|
|
同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 参考文档
|
2018-07-27 13:33:34 +08:00
|
|
|
|
|
|
|
|
|
- [HashMap? ConcurrentHashMap? 相信看完这篇没人能难住你!](https://crossoverjie.top/2018/07/23/java-senior/ConcurrentHashMap/)
|
|
|
|
|
|
2018-08-02 15:58:10 +08:00
|
|
|
|
- [Java多线程之CAS](https://blog.csdn.net/u010412719/article/details/52053390)
|
|
|
|
|
|
|
|
|
|
- [Java中this和super的用法总结](https://www.cnblogs.com/hasse/p/5023392.html)
|