留学生大佬面经三名狂客

1,·CHROME给每个tab开了进程,为什么?其实就是问线程与进程区别:

··进程是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是可以独立运行的一段程序。

·线程是进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源。在运行时,只是暂用一些计数器、寄存器和栈。

·调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。

·并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。

·拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。

·关于进程和线程,首先从定义上理解就有所不同:

1.进程是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是可以独立运行的一段程序。

2.线程是进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源。在运行时,只是暂用一些计数器、寄存器和栈。

·

他们之间的关系

1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程(通常说的主线程)。

2.资源分配给进程,同一进程的所有线程共享该进程的所有资源。

3.线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。

4.处理机分给线程,即真正在处理机上运行的是线程。

5.线程是指进程内的一个执行单元,也是进程内的可调度实体。

从三个角度来剖析二者之间的区别

1.调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。

2.并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。

3.拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。

·共享变量

·wait/notify机制

·Lock/Condition机制

·管道

·线程间发送信号的一个简单方式是在共享对象的变量里设置信号值。线程A在一个同步块里设置boolean型成员变量hasDataToProcess为true,线程B也在同步块里读取hasDataToProcess这个成员变量。这个简单的例子使用了一个持有信号的对象,并提供了set和check方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

publicclassMySignal{

protectedbooleanhasDataToProcess=false;

publicsynchronizedbooleanhasDataToProcess(){

returnthis.hasDataToProcess;

}

publicsynchronizedvoidsetHasDataToProcess(booleanhasData){

this.hasDataToProcess=hasData;

·线程A和B必须获得指向一个MySignal共享实例的引用,以便进行通信。如果它们持有的引用指向不同的MySingal实例,那么彼此将不能检测到对方的信号。需要处理的数据可以存放在一个共享缓存区里,它和MySignal实例是分开存放的。

·为了实现线程通信,我们可以使用Object类提供的wait()、notify()、notifyAll()三个方法。调用wait()方法会释放对该同步监视器的锁定。这三个方法必须由同步监视器对象来调用,这可分成两种情况:

o对于使用synchronized修饰的同步方法,因为该类的默认实例是(this)就是同步监视器,所以可以直接调用这三使用个方法。

o对于synchronized修饰的同步代码块,同步监视器是synchronized括号里的对象,所以必须使用该对象调用这三个方法。

假设系统中有两条线程,这两条线程分别代表取钱者和存钱者。现在系统有一种特殊的要求,系统要求存款者和取钱者不断的实现存款和取钱动作,而且要求每当存款者将钱存入指定账户后,取钱者立即将钱取走.不允许存款者两次存钱,也不允许取钱者两次取钱。我们通过设置一个旗标来标识账户中是否已有存款,有就为true,没有就标为false。具体代码如下:

首先我们定义一个Account类,这个类中有取钱和存钱的两个方法,由于这两个方法可能需要并发的执行取钱、存钱操作,所有将这两个方法都修改为同步方法.(使用synchronized关键字)。

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

publicclassAccount{

privateStringaccountNo;

privatedoublebalance;

//标识账户中是否有存款的旗标

privatebooleanflag=false;

publicAccount(){

super();

publicAccount(StringaccountNo,doublebalance){

this.accountNo=accountNo;

this.balance=balance;

publicsynchronizedvoiddraw(doubledrawAmount){

try{

if(!flag){

this.wait();

}else{

//取钱

System.out.println(Thread.currentThread().getName()+"取钱:"+drawAmount);

balance=balance-drawAmount;

System.out.println("余额:"+balance);

//将标识账户是否已有存款的标志设为false

flag=false;

//唤醒其它线程

this.notifyAll();

}catch(Exceptione){

e.printStackTrace();

publicsynchronizedvoiddeposit(doubledepositAmount){

if(flag){

else{

System.out.println(Thread.currentThread().getName()+"存钱"+depositAmount);

balance=balance+depositAmount;

System.out.println("账户余额为:"+balance);

flag=true;

//TODO:handleexception

·接下来创建两个线程类,分别为取钱和存钱线程!

·取钱线程类:

publicclassDrawThreadimplementsRunnable{

privateAccountaccount;

privatedoubledrawAmount;

publicDrawThread(Accountaccount,doubledrawAmount){

this.account=account;

this.drawAmount=drawAmount;

publicvoidrun(){

for(inti=0;i<100;i++){

account.draw(drawAmount);

·存钱线程类:

publicclassdepositThreadimplementsRunnable{

privatedoubledepositAmount;

publicdepositThread(Accountaccount,doubledepositAmount){

this.depositAmount=depositAmount;

account.deposit(depositAmount);

·最后我们测试一下这个取钱和存钱的操作

publicclassTestDraw{

publicstaticvoidmain(String[]args){

//创建一个账户

Accountaccount=newAccount();

newThread(newDrawThread(account,800),"取钱者").start();

newThread(newdepositThread(account,800),"存款者甲").start();

newThread(newdepositThread(account,800),"存款者乙").start();

newThread(newdepositThread(account,800),"存款者丙").start();

·大致的输出结果如下

存款者甲存钱800.0

账户余额为:800.0

取钱者取钱:800.0

余额:0.0

存款者丙存钱800.0

·如何程序不使用synchronized关键字来保持同步,而是直接适用Lock对像来保持同步,则系统中不存在隐式的同步监视器对象,也就不能使用wait()、notify()、notifyAll()来协调线程的运行.

·当使用LOCK对象保持同步时,Java为我们提供了Condition类来协调线程的运行。关于Condition类,JDK文档里进行了详细的解释.,再次就不啰嗦了。

·我们就拿Account类进行稍微的修改一下吧!

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

importjava.util.concurrent.locks.Condition;

importjava.util.concurrent.locks.Lock;

importjava.util.concurrent.locks.ReentrantLock;

//显示定义Lock对象

privatefinalLocklock=newReentrantLock();

//获得指定Lock对象对应的条件变量

privatefinalConditioncon=lock.newCondition();

publicvoiddraw(doubledrawAmount){

//加锁

lock.lock();

//this.wait();

con.await();

//this.notifyAll();

con.signalAll();

finally{

lock.unlock();

publicvoiddeposit(doubledepositAmount){

}finally{

·输出结果和上面是一样的!只不过这里显示的使用Lock对像来充当同步监视器,使用Condition对象来暂停指定线程,唤醒指定线程!

管道流是JAVA中线程通讯的常用方式之一,基本流程如下:

1.

创建管道输出流PipedOutputStreampos和管道输入流PipedInputStreampis

2.

3.

将pos和pis匹配,pos.connect(pis);

4.

5.

将pos赋给信息输入线程,pis赋给信息获取线程,就可以实现线程间的通讯了

6.

81

82

83

84

85

86

87

importjava.io.IOException;

importjava.io.PipedInputStream;

importjava.io.PipedOutputStream;

publicclasstestPipeConnection{

/**

*创建管道输出流

*/

PipedOutputStreampos=newPipedOutputStream();

*创建管道输入流

PipedInputStreampis=newPipedInputStream();

*将管道输入流与输出流连接此过程也可通过重载的构造函数来实现

pos.connect(pis);

}catch(IOExceptione){

*创建生产者线程

Producerp=newProducer(pos);

*创建消费者线程

Consumer1c1=newConsumer1(pis);

*启动线程

p.start();

c1.start();

*

classProducerextendsThread{

privatePipedOutputStreampos;

publicProducer(PipedOutputStreampos){

this.pos=pos;

inti=0;

while(true)

{

this.sleep(3000);

pos.write(i);

i++;

classConsumer1extendsThread{

privatePipedInputStreampis;

publicConsumer1(PipedInputStreampis){

this.pis=pis;

System.out.println("consumer1:"+pis.read());

·程序启动后,就可以看到producer线程往consumer1线程发送数据

consumer1:0

consumer1:1

consumer1:2

consumer1:3

......

管道流虽然使用起来方便,但是也有一些缺点

o

管道流只能在两个线程之间传递数据。线程consumer1和consumer2同时从pis中read数据,当线程producer往管道流中写入一段数据后,每一个时刻只有一个线程能获取到数据,并不是两个线程都能获取到producer发送来的数据,因此一个管道流只能用于两个线程间的通讯。不仅仅是管道流,其他IO方式都是一对一传输。

管道流只能实现单向发送,如果要两个线程之间互通讯,则需要两个管道流。可以看到上面的例子中,线程producer通过管道流向线程consumer发送数据,如果线程consumer想给线程producer发送数据,则需要新建另一个管道流pos1和pis1,将pos1赋给consumer1,将pis1赋给producer,具体例子本文不再多说。

·管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。

·命名管道(namedpipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。

·信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;Linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。

·消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列systemV消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺

·共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

·内存映射(mappedmemory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。

·信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。

·套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:linux和SystemV的变种都支持套接字。

·个人介绍

··springMVC拦截器和过滤器的区别

··excel导出功能如何实现

··SpringIOC和AOP,动态代理实现方式

··自动装配有哪几种方式,自动装配有什么局限性

模式

说明

Default

在每个bean中都一个autowire=default的默认配置它的含义是:

采用beans和跟标签中的default-autowire="属性值"一样的设置。

On

不使用自动装配,必须通过ref元素指定依赖,默认设置。

ByNname

根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配。例如,在bean定义中将autowire设置为byname,而该bean包含master属性(同时提供setMaster(..)方法),Spring就会查找名为master的bean定义,并用它来装配给master属性。

Bytype

如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。如果存在多个该类型的bean,那么将会抛出异常,并指出不能使用byType方式进行自动装配。若没有找到相匹配的bean,则什么事都不发生,属性也不会被设置。如果你不希望这样,那么可以通过设置dependency-check="objects"让Spring抛出异常。

Constructor

与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。

Antodetect

通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。

注意:

byName和byType

在使用的过程中必须保证bean能够初始化,否则的话会出现bug

如果有默认的无参数的构造器就不需要多余的配置

如果有带有参数的构造器,那在bean的配置中必须配置器初始化的参数或者在bean中添加无参数的构造器

基本类型不可以装配,精准度易混乱bean必须可以获得

··数据库引擎,Innodb,MyISAM的区别

1.MySQL默认采用的是MyISAM。

2.MyISAM不支持事务,而InnoDB支持。InnoDB的AUTOCOMMIT默认是打开的,即每条SQL语句会默认被封装成一个事务,自动提交,这样会影响速度,所以最好是把多条SQL语句显示放在begin和commit之间,组成一个事务去提交。

4.InnoDB支持外键,MyISAM不支持。

5.InnoDB的主键范围更大,最大是MyISAM的2倍。

6.InnoDB不支持全文索引,而MyISAM支持。全文索引是指对char、varchar和text中的每个词(停用词除外)建立倒排序索引。MyISAM的全文索引其实没啥用,因为它不支持中文分词,必须由使用者分词后加入空格再写到数据表里,而且少于4个汉字的词会和停用词一样被忽略掉。

7.MyISAM支持GIS数据,InnoDB不支持。即MyISAM支持以下空间数据对象:Point,Line,Polygon,Surface等。

8.没有where的count(*)使用MyISAM要比InnoDB快得多。因为MyISAM内置了一个计数器,count(*)时它直接从计数器中读,而InnoDB必须扫描全表。所以在InnoDB上执行count(*)时一般要伴随where,且where中要包含主键以外的索引列。为什么这里特别强调“主键以外”?因为InnoDB中primaryindex是和rawdata存放在一起的,而secondaryindex则是单独存放,然后有个指针指向primarykey。所以只是count(*)的话使用secondaryindex扫描更快,而primarykey则主要在扫描索引同时要返回rawdata时的作用较大。

··索引实现方式,B+树有什么特点,B树和B+数的区别,B+树的实现方式

··索引的最左配原则

··HashMap和HashSet的区别,HashMap是有序的吗

··LinkedHashMap,保证什么有序,底层实现。

··java多线程的方式,FutureTaskCallAble介绍,CallAble和Runnable的区别

··线程池

··类的加载过程,双亲委派机制

1.自我介绍?

分布式缓存的典型应用场景可分为以下几类:

1)页面缓存.用来缓存Web页面的内容片段,包括HTML、CSS和图片等,多应用于社交网站等;

2)应用对象缓存.缓存系统作为ORM框架的二级缓存对外提供服务,目的是减轻数据库的负载压力,加速应用访问;

3)状态缓存.缓存包括Session会话状态及应用横向扩展时的状态数据等,这类数据一般是难以恢复的,对可用性要求较高,多应用于高可用集群;

4)并行处理.通常涉及大量中间计算结果需要共享;

5)事件处理.分布式缓存提供了针对事件流的连续查询(continuousquery)处理技术,满足实时性需求;

6)极限事务处理.分布式缓存为事务型应用提供高吞吐率、低延时的解决方案,支持高并发事务请求处理,多应用于铁路、金融服务和电信等领域.

3.你实习的时候JDK用的是那个版本,这个版本有什么新的特性?

Jdk7的新特性:

1.对集合类的语言支持;(??)

2.自动资源管理;

3.改进的通用实例创建类型推断;(??)

4.数字字面量下划线支持;(√)

5.switch中使用string;(√)

JSR292的实现增加了一个InvokeDynamic的字节码指令来支持动态类型语言,使得在把源代码编译成字节码时并不需要确定方法的签名,即方法参数的类型和返回类型。当运行时执行InvokeDynamic指令时,JVM会通过新的动态链接机制MethodHandles,寻找到真实的方法。

为了防止自定义多线程ClassLoad产生的死锁问题,java.lang.ClassLoader类增加了以下API。

4.G1回收器和其他回收器有什么区别?

并发与并行,部分代自己就可以,局部复制全局标记整理堆>4G会比较好。

Java8update20所引入的一个很棒的优化就是G1回收器中的字符串去重(Stringdeduplication)。由于字符串(包括它们内部的char[]数组)占用了大多数的堆空间,这项新的优化旨在使得G1回收器能识别出堆中那些重复出现的字符串并将它们指向同一个内部的char[]数组,以避免同一个字符串的多份拷贝,那样堆的使用效率会变得很低。你可以使用-XX:+UseStringDeduplication这个JVM参数来试一下这个特性。

Java8中最大的改变就是持久代的移除,它原本是用来给类元数据,驻留字符串,静态变量来分配空间的。这在以前都是需要开发人员来针对那些会加载大量类的应用来专门进行堆比例的优化及调整。许多年来都是如此,这也正是许多OutOfMemory异常的根源,因此由JVM来接管它真是再好不过了。即便如此,它本身并不会减少开发人员将应用解耦到不同的JVM中的可能性。

5.垃圾回收为什么会停顿?哪些对象可能作为GCRoots

虚拟机栈中引用的对象方法区(静态属性,常量引用的对象)本地方法栈中引用的对象。

6.垃圾回收分代收集算法?为什么会有两个Survivor区?new一个对象会保存在哪里?

Survivor的存在意义,就是减少被送到老年代的对象,进而减少FullGC的发生,Survivor的预筛选保证,只有经历16次MinorGC还能在新生代中存活的对象,才会被送到老年代。

设置两个Survivor区最大的好处就是解决了碎片化

7.Java内存模型volatile关键字,使用场景?原子性的理解?先行发生原则?

Java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存(可以与前面将的处理器的高速缓存类比),线程的工作内存中保存了该线程使用到的变量到主内存副本拷贝,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量。

·lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。

·unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。

·read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用

·load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。

·use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。

·assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。

·store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。

·write(写入):作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中。

如果要把一个变量从主内存中复制到工作内存,就需要按顺寻地执行read和load操作,如果把变量从工作内存中同步回主内存中,就要按顺序地执行store和write操作。Java内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行。也就是read和load之间,store和write之间是可以插入其他指令的,如对主内存中的变量a、b进行访问时,可能的顺序是reada,readb,loadb,loada。Java内存模型还规定了在执行上述八种基本操作时,必须满足如下规则:

·不允许read和load、store和write操作之一单独出现

·不允许一个线程丢弃它的最近assign的操作,即变量在工作内存中改变了之后必须同步到主内存中。

·不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步回主内存中。

·一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量。即就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。

·一个变量在同一时刻只允许一条线程对其进行lock操作,lock和unlock必须成对出现

·如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值

·如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。

·对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。

1.作为状态标志

2.一次性安全发布

3.独立观察

4.volatilebean模式

5.开销较低的读写锁策略

Java内存模型中存在的天然的先行发生关系:

1.程序次序规则:同一个线程内,按照代码出现的顺序,前面的代码先行于后面的代码,准确的说是控制流顺序,因为要考虑到分支和循环结构。

4.线程启动规则:Thread的start()方法先行发生于这个线程的每一个操作。

5.线程终止规则:线程的所有操作都先行于此线程的终止检测。可以通过Thread.join()方法结束、Thread.isAlive()的返回值等手段检测线程的终止。

6.线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupt()方法检测线程是否中断

7.对象终结规则:一个对象的初始化完成先行于发生它的finalize()方法的开始。

8.传递性:如果操作A先行于操作B,操作B先行于操作C,那么操作A先行于操作C。

8.场景题:现在有三个线程,同时start,用什么方法可以保证线程执行的顺序,线程一执行完线程二执行,线程二执行完线程三执行?

packagecom.wenjie.threadDemo;

publicclassJionTest{

finalThreadt1=newThread(newRunnable(){

//TODOAuto-generatedmethodstub

System.out.println("t1");

});

finalThreadt2=newThread(newRunnable(){

t1.join();

}catch(InterruptedExceptione){

//TODOAuto-generatedcatchblock

System.out.println("t2");

finalThreadt3=newThread(newRunnable(){

t2.join();

System.out.println("t3");

t2.start();

t3.start();

t1.start();

9.你是怎么理解线程安全的?HashMap是线程安全的么?如果多个线程同时修改HashMap时会发生什么情况?

Failfast

死锁

异常concurrentmodeex

11.静态代理和动态代理的区别?动态代理是怎么实现的?

13.你做过hadoop的项目,为什么要用hadoop?你们处理的文件是什么格式的?写了几个mapper几个reducer?

Hbase,json

15.TCP首部?TCP为什么是可靠的?三次握手四次挥手?

TCP提供一种面向连接的、可靠的字节流服务。

面向连接:意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接。在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP。

TCP通过下列方式来提供可靠性:

1、应用数据被分割成TCP认为最适合发送的数据块。这和UDP完全不同,应用程序产生的数据报长度将保持不变。(将数据截断为合理的长度)

2、当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

(超时重发)

3、当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。(对于收到的请求,给出确认响应)(之所以推迟,可能是要对包做完整校验)

4、TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。(校验出包有错,丢弃报文段,不给出响应,TCP发送数据端,超时时会重发数据)

5、既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。(对失序数据进行重新排序,然后才交给应用层)

6、既然IP数据报会发生重复,TCP的接收端必须丢弃重复的数据。(对于重复数据,能够丢弃重复数据)

7、TCP还能提供流量控制。TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。(TCP可以进行流量控制,防止较快主机致使较慢主机的缓冲区溢出)TCP使用的流量控制协议是可变大小的滑动窗口协议。

字节流服务::

两个应用程序通过TCP连接交换8bit字节构成的字节流。TCP不在字节流中插入记录标识符。我们将这称为字节流服务(bytestreamservice)。

TCP对字节流的内容不作任何解释::TCP对字节流的内容不作任何解释。TCP不知道传输的数据字节流是二进制数据,还是ASCII字符、EBCDIC字符或者其他类型数据。对字节流的解释由TCP连接双方的应用层解释。

17.你平时喜欢做什么?看过哪些书?最近在看什么书?(这里有个段子,我:最近在看《HTTP权威指南》。面试官:什么?HTTP潜规则?我:???)

柯南东野圭吾

舞蹈运动电影

二面:(8月2号晚上:视频面试:47分钟)

1.你那边怎么有点黑啊?(我靠,我也想说啊,暑假寝室集中供电,然而我们寝室没有电。发面经也不忘吐槽学校,简直坑啊。。。抱着台灯瑟瑟发抖。。。)

2.现在在哪里实习?实习主要做些什么?

3.说一下Java里面你最感兴趣的一个部分?

并发?

4.熟悉Java的哪些框架?用了Spring的哪些东西?Spring现在最新的版本是多少?

5.讲一下MVC设计模式,有什么框架用到了这个模式?spring

6.场景题:一个Controller调用两个Service,这两Service又都分别调用两个Dao,问其中用到了几个数据库连接池的连接?

7.安全方面:如何防止SQL注入?如何防止用户删除其他用户的信息?表单提交可以跨域么?自己写的接口如何防止被其他人恶意调用?

防止被恶意调用的话,可以做请求限制,第一次请求返回一个随机数,下次请求把随机数带过来,返回时再返回一个随机数

8.zookeeper偶数选举问题?(感觉很重视zookeeper啊)

9.hadoop为什么要将文件分块并且复制三份,复制两份不行么?这样不浪费空间么?namenode脑裂问题?zookeeper如何管理全局配置文件?你们的Hadoop项目用到了几台机器,每个机器的作用?

10.Servlet是线程安全的么?

11.创建一个对象的详细过程?其中发生了些什么?

12.JavaNIO你了解么?讲一讲你最熟悉的部分?

14.你认为你身边的同学怎么样?如果你正在打游戏,你想让同学帮忙带瓶水,你觉得有多少人会帮你带?(这又是什么套路?让我去送水?)

15.你还有什么想问的?

三面:(HR面,8月4号下午:视频面试:22分钟)

1.7岁一个阶段,说一说每一个阶段对你影响最大的一个人或事?

2.说一下你大学阶段做了些什么?

3.你感觉你前两个面试官怎么样?

4.春招的时候为什么没有去bat实习?

5.你当初准备暑期实习的话,是想学到些什么?现在感觉自己有哪些进步?

6.你还有什么想问的?(当然是万能的培养计划和晋升机制)

1.自我介绍?2.说一下最能代表你技术水平的项目吧?

3.maven如何进行依赖管理,如何解决依赖冲突?

1.依赖是使用Maven坐标来定位的,而Maven坐标主要由GAV(groupId,artifactId,version)构成。如果两个相同的依赖包,如果groupId,artifactId,version不同,那么maven也认为这两个是不同的。

2.依赖会传递,A依赖了B,B依赖了C,那么A的依赖中就会出现B和C。

3.Maven对同一个groupId,artifactId的冲突仲裁,不是以version越大越保留,而是依赖路径越短越优先,然后进行保留。

4.依赖的scope会影响依赖的影响范围。

1.确定出了问题的jar包名称。通常可以在eclipse中查找冲突的类有在哪些依赖包里面出现了。并确定实际要使用的是那个包,冲突的包有哪些。

2.通过mvndependency:tree>tree.txt导出全部的依赖。

4.找到相互冲突的并需要排除的依赖的顶级依赖,并分析冲突的原因,冲突的原因可能是以下几种:

·同一个jar包但groupId,artifactId不同,这种冲突只能通过设定依赖的来进行排除

·需要的版本jar包依赖路径较长,这种冲突可以把想要版本的依赖直接什么在依赖中,这样路径就最短了优先级最高。

5.最后可以通过打包mvninstall来确认打出来的war包中是否有被排除的依赖。

4.maven的源和插件了解哪些?maven的生命周期?

5.如何保证分布式缓存的一致性?分布式session实现?

6.spring的bean的创建时机?依赖注入的时机?

7.你们的图片时怎么存储的,对应在数据库中时如何保存图片的信息的?

9.项目中用到的JDK的哪些特性?

10.java8流式迭代的好处?

11.多线程如何在多个CPU上分布?线程调度算法有哪些?

12.线程调度和进程调度的区别?

13.项目中用到了哪些集合类?

14.说一下TreeMap的实现原理?红黑树的性质?红黑树遍历方式有哪些?如果key冲突如何解决?setColor()方法在什么时候用?什么时候会进行旋转和颜色转换?后者覆盖前者保持唯一性

15.你有什么想问的?

下面将最近面试遇到的一些题目进行汇总如下,希望对现在正在找工作的同学和现在面临毕业找工作的同学有所帮助。

单例模式:懒汉式、饿汉式、双重校验锁、静态加载,内部类加载、枚举类加载。保证一个类仅有一个实例,并提供一个访问它的全局访问点。

代理模式:动态代理和静态代理,什么时候使用动态代理。

适配器模式:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

装饰者模式:动态给类加功能。

观察者模式:有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。

外观模式:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

命令模式:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。

创建者模式:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

Set、List、Map的区别和联系

什么时候使用HashMap

什么时候使用LinkedHashMap、ConcurrentHashMap、WeakHashMap

哪些集合类是线程安全的

为什么Set、List、Map不实现Cloneable和Serializable接口

ConcurrentHashMap的实现,1.7和1.8的实现

Arrays.sort的实现

什么时候使用CopyOnArrayList

volatile的使用

Synchronied的使用

ReentrantLock的实现以及和Synchronied的区别

CAS的实现原理以及问题

AQS的实现原理

接口和抽象类的区别,什么时候使用

类加载机制的步骤,每一步做了什么,static和final修改的成员变量的加载时机

双亲委派模型

反射机制:反射动态擦除泛型、反射动态调用方法等

动态绑定:父类引用指向子类对象

JVM内存管理机制:有哪些区域,每个区域做了什么

JVM垃圾回收机制:垃圾回收算法垃圾回收器垃圾回收策略

jvm参数的设置和jvm调优

什么情况产生年轻代内存溢出、什么情况产生年老代内存溢出

内部类:静态内部类和匿名内部类的使用和区别

redis和memcached:什么时候选择redis,什么时候选择memcached,内存模型和存储策略是什么样的

mysql的优化策略有哪些

mysql索引的实现B+树的实现原理

什么情况索引不会命中,会造成全表扫描

java中bionioaio的区别和联系

为什么bio是阻塞的nio是非阻塞的nio的模型是什么样的

Reactor模型和Proactor模型

linux命令统计,排序,前几问题等

StringBuff和StringBuilder的实现,底层实现是通过byte数据,外加数组的拷贝来实现的

cas操作的使用

内存缓存和数据库的一致性同步实现

微服务的优缺点

线程池的参数问题

ip问题如何判断ip是否在多个ip段中

判断数组两个中任意两个数之和是否为给定的值

乐观锁和悲观锁的实现

synchronized实现原理

你在项目中遇到的困难和怎么解决的

你在项目中完成的比较出色的亮点

消息队列广播模式和发布/订阅模式的区别

生产者消费者代码实现

死锁代码实现

线程池:参数,每个参数的作用,几种不同线程池的比较,阻塞队列的使用,拒绝策略

常见序列化协议及其优缺点

memcached内存原理,为什么是基于块的存储

搭建一个rpc需要准备什么

如果线上服务器频繁地出现fullgc,如何去排查

如果某一时刻线上机器突然量变得很大,服务扛不住了,怎么解决

LRU算法的实现

LinkedHashMap实现LRU

定义栈的数据结构,请在该类型中实现一个能够找到栈最小元素的min函数

海量数据处理的解决思路

reactor模型的演变

阻塞、非阻塞、同步、异步区别

Collection的子接口

linux命令,awk、cat、sort、cut、grep、uniq、wc、top等

你觉得你的优点是什么,你的缺点是什么,为什么我们要录用你

Springmvc的实现原理

netty底层实现,IO模型,ChannelPipeline的实现和原理

缓存的设计和优化

缓存和数据库一致性同步解决方案

你所在项目的系统架构,谈谈整体实现

消息队列的使用场景

ActiveMQ、RabbitMQ、Kafka的区别

JVM内存分配策略和垃圾回收时机

JVM垃圾回收策略和对象的实际生命周期

对象是如何在堆中分配的

fullgc触发的场景,线上如果一直fullgc怎么排查

如何防止接口被恶意攻击

线上某一台服务器出现问题,如何实际操作去解决

线上接口最大的QPS以及如何评估服务器可承受的最大请求数

内存缓存的使用场景和优缺点

怎么防止线上接口被恶意刷

怎么防止线上接口被攻击

栈帧的结构

transient关键字的使用

hashMap可以key为空或者value为空吗?可以同时为空吗?

HashSet有什么特点?

话题二:

HashMap底层是怎么实现的?

1.6:数组+链表

1.8:数组+链表/红黑树

为什么要二次hash?谈谈扩容|什么时候扩容?

HashMap与Hashtable有什么区别吗?

Hashtable加同步锁有什么问题?能不能有更好的实现方式?

ConcurrentHashMap底层怎么实现的?怎么保证同步的(CAS)?

话题三:

如果前面的,你都答出来了?

什么是CAS?它synchronized有什么区别?

谈谈synchronized?

能谈一下volatile吗?

6、JVM连环炮+并发编程?

话题一:

1、谈谈内存区域?

堆、栈、方法区、(程序计算器、本地方法栈)|可以不谈

2、堆、栈、方法区分别有什么用?存储什么内容?

3、能谈谈堆吗?

新生代、老年代

4、怎么判断对象不可用?

5、能谈一下GC策略吗?它是怎么回收不可用对象的?

标记-清除,复制、标记-整理、分代。

6、能谈一下垃圾回收器吗(暂无碰见问的)

7、对象怎么分配的?

1、谈一下类加载过程?

2、谈一下双亲委派机制?

1、谈一下Java内存模型

2、谈一下Synchronized、volatile?

2、谈一下AQS、CountDownLatch、ReentrantLock?(暂时还没有人问)

3、谈一下ThreadLocal?

4、谈一下CAS?

5、谈一下线程池原理?

二、设计模式

1、谈一下六种设计原则?开闭原则什么意思?里氏XX是什么意思?

2、写一个单例模式?后续自己扩展各种的优缺点?

3、谈一个你熟悉的设计模式?

三、缓存

1、设计一个高效的缓存?

2、谈谈LRU算法?(解决高效的缓存)

三、架构思想、高并发、大数据量解决方案。

1、一个很大的日记文件,统计出访问排行?

2、mapreduce思想?谈谈shuffle?

1、unordered_map的实现原理。。很具体的描述

2、单链表多路归并排序

有一个场景,现在cache满了,需要淘汰频率最低的那个

更新:0824华为

关于HTTP请求GET和POST的区别

1.GET提交,请求的数据会附在URL之后(就是把数据放置在HTTP协议头<request-line>中),以分割URL和传输数据,多个参数用&连接;例如:login.actionname=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。

POST提交:把提交的数据放置在是HTTP包的包体<request-body>中。上文示例中红色字体标明的就是实际的传输数据

因此,GET提交的数据会在地址栏中显示出来,而POST提交,地址栏不会改变

2.传输数据的大小:

GET:特定浏览器和服务器对URL长度有限制,例如IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系统的支持。

因此对于GET提交时,传输数据就会受到URL长度的限制。

POST:由于不是通过URL传值,理论上数据不受限。但实际各个WEB服务器会规定对post提交数据大小进行限制,Apache、IIS6都有各自的配置。

3.安全性:

Http协议:一个HTTP请求报文由请求行(requestline)、请求头部(header)、空行和请求数据4个部分组成,下图给出了请求报文的一般格式。

请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET/index.htmlHTTP/1.1。

请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:

User-Agent:产生请求的浏览器类型。

Accept:客户端可识别的内容类型列表。

Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。

HTTP响应也由三个部分组成,分别是:状态行、消息报头、响应正文。

HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。

HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

HTTPS和HTTP的区别主要如下:

对称密码加解密,非对称密码加解密。

事务隔离级别和实现方式。

遇到问题:分布式加锁问题:

memcached分布式锁:1、实现原理:

memcached带有add函数,利用add函数的特性即可实现分布式锁。add和set的区别在于:如果多线程并发set,则每个set都会成功,但最后存储的值以最后的set的线程为准。而add的话则相反,add会添加第一个到达的值,并返回true,后续的添加则都会返回false。利用该点即可很轻松地实现分布式锁。

2、优点

并发高效。

3、缺点

效率对库依赖比较重,重量级

(1)memcached采用列入LRU置换策略,所以如果内存不够,可能导致缓存中的锁信息丢失。

(2)memcached无法持久化,一旦重启,将导致信息丢失。

Redis:redis分布式锁即可以结合zk分布式锁锁高度安全和memcached并发场景下效率很好的优点,可以利用jedis客户端实现。

URL到页面相应的全过程:

浏览器缓存etc缓存路由缓存服务提供商缓存递归到根dns,请求连接TCP。发送报文,恢复

SpringAOP开发用到了那些部分?

==一般只用到了基本数据类型比较

1、equals方法用于比较对象的内容是否相等(覆盖以后)

2、hashcode方法只有在集合中用到

3、当覆盖了equals方法时,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否相等)。

4、将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。

J2SE基础

1.九种基本数据类型的大小,以及他们的封装类。

基本类型

大小(字节)

默认值

封装类

byte

(byte)0

Byte

short

(short)0

Short

int

0

Integer

long

0L

Long

float

0.0f

Float

double

0.0d

Double

boolean

-

false

Boolean

char

\u0000(null)

Character

void

Void

2.Switch能否用string做参数?

3.equals与==的区别。

4.Object有哪些公用方法?

Waitnotifynotifyallcloneequelsgetclass

5.Java的四种引用,强弱软虚,用到的场景。

6.Hashcode的作用。

7.ArrayList、LinkedList、Vector的区别。

8.String、StringBuffer与StringBuilder的区别。

9.Map、Set、List、Queue、Stack的特点与用法。

10.HashMap和HashTable的区别。

11.HashMap和ConcurrentHashMap的区别,HashMap的底层源码。

12.TreeMap、HashMap、LindedHashMap的区别。

13.Collection包结构,与Collections的区别。

14.trycatchfinally,try里有return,finally还执行么?

15.Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况。

16.Java面向对象的三个特征与含义。

17.Override和Overload的含义去区别。

18.Interface与abstract类的区别。

19.Staticclass与nonstaticclass的区别。

20.java多态的实现原理。

同一操作不同结果,前期绑定后期绑定

21.实现多线程的两种方法:Thread与Runable。Call

22.线程同步的方法:sychronized、lock、reentrantLock等。

23.锁的等级:方法锁、对象锁、类锁。

24.写出生产者消费者模式。

25.ThreadLocal的设计理念与作用。ThreadThreadLocal->ThreadLocalMap

26.ThreadPool用法与优势。

27.Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。

28.wait()和sleep()的区别。

29.foreach与正常for循环效率对比。

30.JavaIO与NIO。

31.反射的作用于原理。

32.泛型常用特点,List能否转为List

33.解析XML的几种方式的原理与特点:DOM、SAX、PULL。

34.Java与C++对比。

35.Java1.7与1.8新特性。

36.设计模式:单例、工厂、适配器、责任链、观察者等等。

37.JNI的使用。

Java里有很多很杂的东西,有时候需要你阅读源码,大多数可能书里面讲的不是太清楚,需要你在网上寻找答案。

推荐书籍:《java核心技术卷I》《Thinkinginjava》《java并发编程》《effictivejava》《大话设计模式》

JVM

1.内存模型以及分区,需要详细到每个区放什么。

2.堆里面的分区:Eden,survivalfromto,老年代,各自的特点。

3.对象创建方法,对象的内存分配,对象的访问定位。

4.GC的两种判定方法:引用计数与引用链。

5.GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?

6.GC收集器有哪些?CMS收集器与G1收集器的特点。

7.MinorGC与FullGC分别在什么时候发生?

8.几种常用的内存调试工具:jmap、jstack、jconsole。

9.类加载的五个过程:加载、验证、准备、解析、初始化。

10.双亲委派模型:BootstrapClassLoader、ExtensionClassLoader、ApplicationClassLoader。

11.分派:静态分派与动态分派。

JVM过去过来就问了这么些问题,没怎么变,内存模型和GC算法这块问得比较多,可以在网上多找几篇博客来看看。

推荐书籍:《深入理解java虚拟机》

操作系统

1.进程和线程的区别。

2.死锁的必要条件,怎么处理死锁。

3.Window内存管理方式:段存储,页存储,段页存储。

4.进程的几种状态。

5.IPC几种通信方式。

6.什么是虚拟内存。

7.虚拟地址、逻辑地址、线性地址、物理地址的区别。

因为是做android的这一块问得比较少一点,还有可能上我简历上没有写操作系统的原因。

推荐书籍:《深入理解现代操作系统》

TCP/IP

1.OSI与TCP/IP各层的结构与功能,都有哪些协议。

2.TCP与UDP的区别。

3.TCP报文结构。

4.TCP的三次握手与四次挥手过程,各个状态名称与含义,TIMEWAIT的作用。

5.TCP拥塞控制。

6.TCP滑动窗口与回退N针协议。

7.Http的报文结构。

8.Http的状态码含义。

9.Httprequest的几种类型。

10.Http1.1和Http1.0的区别

11.Http怎么处理长连接。

12.Cookie与Session的作用于原理。

13.电脑上访问一个网页,整个过程是怎么样的:DNS、HTTP、TCP、OSPF、IP、ARP。

14.Ping的整个过程。ICMP报文是什么。

15.C/S模式下使用socket通信,几个关键函数。

16.IP地址分类。

17.路由器与交换机区别。

推荐书籍:《TCP/IP协议族》

数据结构与算法

1.链表与数组。

2.队列和栈,出栈与入栈。

3.链表的删除、插入、反向。

4.字符串操作。

5.Hash表的hash函数,冲突解决方法有哪些。

7.快排的partition函数与归并的Merge函数。

8.对冒泡与快排的改进。

9.二分查找,与变种二分查找。

10.二叉树、B+树、AVL树、红黑树、哈夫曼树。

11.二叉树的前中后续遍历:递归与非递归写法,层序遍历算法。

12.图的BFS与DFS算法,最小生成树prim算法与最短路径Dijkstra算法。

13.KMP算法。

14.排列组合问题。

15.动态规划、贪心算法、分治算法。(一般不会问到)

16.大数据处理:类似10亿条数据找出最大的1000个数.........等等

推荐书籍:《大话数据结构》《剑指offer》《编程之美》

以下是我常问的几个问题,如果需要可以参考:

1.贵公司一向以XXX著称,能不能说明一下公司这方面的特点?

2.贵公司XXX业务发展很好,这是公司发展的重点么?

3.对技术和业务怎么看?

4.贵公司一般的团队是多大,几个人负责一个产品或者业务?

5.贵公司的开发中是否会使用到一些最新技术?

6.对新人有没有什么培训,会不会安排导师?

7.对FullStack怎么看?

8.你觉得我有哪些需要提高的地方?

网易小袁兵总结:

1javaconcurrent包下有哪些类,了解哪些锁2hashmap和concurrenthashmap有什么区别?各自的机制是什么样的?hashmap如何解决链表过长?红黑树有哪些特性?

·*每个结点要么是“红色”,要么是“黑色”(后面将说明)

·*所有的叶结点都是空结点,并且是“黑色”的

·*如果一个结点是“红色”的,那么它的两个子结点都是“黑色”的

·*(注:也就是說,如果結點是黑色的,那么它的子節點可以是紅色或者是黑色的)。

·*结点到其子孙结点的每条简单路径都包含相同数目的“黑色”结点

·*根结点永远是“黑色”的

·之所以称为红黑树的原因就在于它的每个结点都被“着色”为红色或黑色。这些结点颜色被用来检测树的平衡性。但需要注意的是,红黑树并不是平衡二叉树,恰恰相反,红黑树放松了平衡二叉树的某些要求,由于一定限度的“不平衡”,红黑树的性能得到了提升。

·从根结点到叶结点的黑色结点数被称为树的“黑色高度”(black-height)。前面关于红黑树的性质保证了从根结点到叶结点的路径长度不会超过任何其他路径的两倍。

对于给定的黑色高度为n的红黑树,从根到叶结点的简单路径的最短长度为n-1,最大长度为2(n-1)。

3怎么样实现公平锁?实现机制?

同步队列啊有头信息获得锁之前看是否有前驱节点没有获得锁。4java引用类型有哪些?各有什么特点?

就可以他的名字一样,任何时候GC是不能回收他的,哪怕内存不足时,系统会直接抛出异常OutOfMemoryError,也不会去回收,首先要说明的是java中默认就是强引用,

软引用他的特点是当内存足够时不会回收这种引用类型的对象,只有当内存不够用时才会回收,这种特点很适合最一些缓存。

SoftReferencepersonSoftReference=newSoftReference<>(jack);

虚引用的特点是只要GC一运行就会把给回收了,个人感觉没多大用处,因为只要GC一运行他就会被回收了。

WeakReferencepersonSoftReference=newWeakReference(jack);

5遇过哪些内存泄漏的问题?什么原因?

内存泄露是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄露。

1、静态集合类引起内存泄露:像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。例:StaticVectorv=newVector(10);for(inti=1;i<100;i++){Objecto=newObject();v.add(o);o=null;}//在这个例子中,循环申请Object对象,并将所申请的对象放入一个Vector中,如果仅仅释放引用本身(o=null),那么Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。

2、当集合里面的对象属性被修改后,再调用remove()方法时不起作用。

例:publicstaticvoidmain(String[]args){Setset=newHashSet();Personp1=newPerson("唐僧","pwd1",25);Personp2=newPerson("孙悟空","pwd2",26);Personp3=newPerson("猪八戒","pwd3",27);set.add(p1);set.add(p2);set.add(p3);System.out.println("总共有:"+set.size()+"个元素!");//结果:总共有:3个元素!p3.setAge(2);//修改p3的年龄,此时p3元素对应的hashcode值发生改变

set.remove(p3);//此时remove不掉,造成内存泄漏

set.add(p3);//重新添加,居然添加成功System.out.println("总共有:"+set.size()+"个元素!");//结果:总共有:4个元素!for(Personperson:set){System.out.println(person);}}

3、监听器在java编程中,我们都需要和监听器打交道,通常一个应用当中会用到很多监听器,我们会调用一个控件的诸如addXXXListener()等方法来增加监听器,但往往在释放对象的时候却没有记住去删除这些监听器,从而增加了内存泄漏的机会。

5、内部类和外部模块等的引用内部类的引用是比较容易遗忘的一种,而且一旦没释放可能导致一系列的后继类对象没有释放。此外程序员还要小心外部模块不经意的引用,例如程序员A负责A模块,调用了B模块的一个方法如:publicvoidregisterMsg(Objectb);这种调用就要非常小心了,传入了一个对象,很可能模块B就保持了对该对象的引用,这时候就需要注意模块B是否提供相应的操作去除引用。

6、单例模式不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例子:classA{publicA(){B.getInstance().setA(this);}....}//B类采用单例模式classB{privateAa;privatestaticBinstance=newB();publicB(){}publicstaticBgetInstance(){returninstance;}publicvoidsetA(Aa){this.a=a;}//getter...}显然B采用singleton模式,它持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较复杂的对象或者集合类型会发生什么情况

6怎么样实现list的线程安全?

Copyandwritearraylistconcurrent...Vector7怎么样实现一个缓存中的LRU算法?

yes8listhashmap的原理

在理解了#7介绍的HashMap后,我们来学习LinkedHashMap的工作原理及实现。首先还是类似的,我们写一个简单的LinkedHashMap的程序:

LinkedHashMaplmap=newLinkedHashMap();

lmap.put("语文",1);

lmap.put("数学",2);

lmap.put("英语",3);

lmap.put("历史",4);

lmap.put("政治",5);

lmap.put("地理",6);

lmap.put("生物",7);

lmap.put("化学",8);

for(Entryentry:lmap.entrySet()){

System.out.println(entry.getKey()+":"+entry.getValue());

运行结果是:

语文:1

数学:2

英语:3

历史:4

政治:5

地理:6

生物:7

化学:8

我们可以观察到,和HashMap的运行结果不同,LinkedHashMap的迭代输出的结果保持了插入顺序。是什么样的结构使得LinkedHashMap具有如此特性呢?我们还是一样的看看LinkedHashMap的内部结构,对它有一个感性的认识:

没错,正如官方文档所说:

HashtableandlinkedlistimplementationoftheMapinterface,withpredictableiterationorder.ThisimplementationdiffersfromHashMapinthatitmaintainsadoubly-linkedlistrunningthroughallofitsentries.Thislinkedlistdefinestheiterationordering,whichisnormallytheorderinwhichkeyswereinsertedintothemap(insertion-order).

LinkedHashMap是Hash表和链表的实现,并且依靠着双向链表保证了迭代顺序是插入的顺序。

在HashMap中提到了下面的定义:

//CallbackstoallowLinkedHashMappost-actions

voidafterNodeAccess(Nodep){}

voidafterNodeInsertion(booleanevict){}

voidafterNodeRemoval(Nodep){}

LinkedHashMap继承于HashMap,因此也重新实现了这3个函数,顾名思义这三个函数的作用分别是:节点访问后、节点插入后、节点移除后做一些事情。

afterNodeAccess函数

voidafterNodeAccess(Nodee){//movenodetolast

LinkedHashMap.Entrylast;

//如果定义了accessOrder,那么就保证最近访问节点放到最后

if(accessOrder&&(last=tail)!=e){

LinkedHashMap.Entryp=

(LinkedHashMap.Entry)e,b=p.before,a=p.after;

p.after=null;

if(b==null)

head=a;

else

b.after=a;

if(a!=null)

a.before=b;

last=b;

if(last==null)

head=p;

p.before=last;

last.after=p;

tail=p;

++modCount;

就是说在进行put之后就算是对节点的访问了,那么这个时候就会更新链表,把最近访问的放到最后,保证链表。

afterNodeInsertion函数

voidafterNodeInsertion(booleanevict){//possiblyremoveeldest

LinkedHashMap.Entryfirst;

//如果定义了移除规则,则执行相应的溢出

if(evict&&(first=head)!=null&&removeEldestEntry(first)){

Kkey=first.key;

removeNode(hash(key),key,null,false,true);

如果用户定义了removeEldestEntry的规则,那么便可以执行相应的移除操作。

afterNodeRemoval函数

voidafterNodeRemoval(Nodee){//unlink

//从链表中移除节点

p.before=p.after=null;

if(a==null)

tail=b;

这个函数是在移除节点后调用的,就是将节点从双向链表中删除。

我们从上面3个函数看出来,基本上都是为了保证双向链表中的节点次序或者双向链表容量所做的一些额外的事情,目的就是保持双向链表中节点的顺序要从eldest到youngest。

9手写一个算法,随便一个整数num,一个代表进制的整数k(小于10),实现num的k进制转换10实现一个算法,数据库有一个按顺序排列的歌单,用户在前台修改了顺序,现要把数据库的歌单修改成同样的顺序,问怎么样操作最少.11实现一个算法,一个文档有若干单词(内存放不下),现要求出10个频度最高的单词12jvm中适合高吞吐量的垃圾回收器

13cms垃圾回收器的特点14有几种垃圾回收算法15计算机网络osi模型16tcp如何实现拥塞控制和流量控制?具体算法是什么?

HTTP请求消息头部实例:

Host:rss.sina.com.cn

User-Agent:Mozilla/5、0(Windows;U;WindowsNT5、1;zh-CN;rv:1、8、1、14)Gecko/20080404Firefox/2、0、0、14

Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0、9,text/plain;q=0、8,image/png,*/*;q=0、5

Accept-Language:zh-cn,zh;q=0、5

Accept-Encoding:gzip,deflate

Accept-Charset:gb2312,utf-8;q=0、7,*;q=0、7

Keep-Alive:300

Connection:keep-alive

Cookie:userId=C5bYpXrimdmsiQmsBPnE1Vn8ZQmdWSm3WRlEB3vRwTnRtW<--Cookie

If-Modified-Since:Sun,01Jun200812:05:30GMT

Cache-Control:max-age=0

HTTP响应消息头部实例:

Status:OK-200<--响应状态码,表示web服务器处理的结果。

Date:Sun,01Jun200812:35:47GMT

Server:Apache/2、0、61(Unix)

Last-Modified:Sun,01Jun200812:35:30GMT

Accept-Ranges:bytes

Content-Length:18616

Cache-Control:max-age=120

Expires:Sun,01Jun200812:37:47GMT

Content-Type:application/xml

Age:2

X-Cache:HITfrom236-41、D07071951、sina、com、cn<--反向代理服务器使用的HTTP头部

Via:1.0236-41.D07071951.sina.com.cn:80(squid/2.6.STABLE13)

19有哪些非对称加密算法

RSA,EIGamal,ECC,Knapsack,etc.RSA是企业级应用标准,很多第三方的加密软件使用RSA2048bit加密。ECC更高效,164bitECC约等于1024bit的RSA,经常使用在移动设备上。

20linux了解吗?21class字节码文件格式是什么?

ClassFile中的字段简单说明如下:

1、MagicNumber:MagicNumber是用来标志class文件的,虚拟机加载class文件的时候会先检查这四个字节,如果不是cafebabe则虚拟机拒绝加载该文件,这样就可以防止加载非class文件而浪费系统资源。这个字段的长度是4个字节,值是固定的cafebabe。

2、Version:version字段有2个长度都为2字节的字段组成,分别是MajorVersion和MinorVersion,分别代表当前class文件的主版本号和次版本号。随着Java技术的不断发展,Javaclass文件格式会增加一些新的内容来支持Java语言的新特性。同时,不同的虚拟机支持的Javaclass文件的版本范围是不同的,所以在加载class文件之前可以先看看该class文件是否在当前虚拟机的支持范围之内,避免加载不支持的class文件。

3、常量池

首先是2个字节的长度字段constant_pool_count,表明常量池包含了多少个常量。

后面跟着就是constant_pool_count个常量,常量池里放的是字面常量和符号引用。

这里的常量又根据具体的类型分成字符串,整形,长整型,浮点型,双精度浮点型这几种基本类型。

而符号引用保存的是对应的引用的全局限定名,所以保存的是字符串。

4、access_flag保存了当前类的访问权限

5、this_cass保存了当前类的全局限定名在常量池里的索引

6、superclass保存了当前类的父类的全局限定名在常量池里的索引

7、interfaces保存了当前类实现的接口列表,包含两部分内容:interfaces_count和interfaces[interfaces_count]

interfaces_count指的是当前类实现的接口数目

interfaces[]是包含interfaces_count个接口的全局限定名的索引的数组

8、fields保存了当前类的成员列表,包含两部分的内容:fields_count和fields[fields_count]

fields_count是类变量和实例变量的字段的数量总和。

fileds[]是包含字段详细信息的列表。

9、methods保存了当前类的方法列表,包含两部分的内容:methods_count和methods[methods_count]

methods_count是该类或者接口显示定义的方法的数量。

method[]是包含方法信息的一个详细列表。

10、attributes包含了当前类的attributes列表,包含两部分内容:attributes_count和attributes[attributes_count]

class文件的最后一部分是属性,它描述了该类或者接口所定义的一些属性信息。attributes_count指的是attributes列表中包含的attribute_info的数量。

属性可以出现在class文件的很多地方,而不只是出现在attributes列表里。如果是attributes表里的属性,那么它就是对整个class文件所对应的类或者接口的描述;如果出现在fileds的某一项里,那么它就是对该字段额外信息的描述;如果出现在methods的某一项里,那么它就是对该方法额外信息的描述。22模拟一个数据库死锁?如何解决死锁问题

28类加载机制是什么,为什么实现双亲委派模型?

30分布式的二阶段提交算法

可用于分布式任务

31post和get有什么区别32ThreadLocal有什么问题内存溢出this.thread->threadlocalmap->(threadlocal实例,然后value)33不加锁实现阻塞队列

2017-9-12

三次握手:

·客户端先发送FIN,进入FIN_WAIT1状态

·服务端收到FIN,发送ACK,进入CLOSE_WAIT状态,客户端收到这个ACK,进入FIN_WAIT2状态

·服务端发送FIN,进入LAST_ACK状态

·客户端收到FIN,发送ACK,进入TIME_WAIT状态,服务端收到ACK,进入CLOSE状态

·客户端TIME_WAIT持续2倍MSL时长,在linux体系中大概是60s,转换成CLOSE状态

回到上面的问题,go写了一个HTTP服务,压测发现TIME_WAIT过多。

首先判断是不是压测程序放在服务的同一台机器...当然不会犯这么低级的错误...

那么这个感觉就有点奇怪了,HTTP服务并没有依赖外部mysql或者redis等服务,就是一个简单的Helloworld,而TIME_WAIT的是主动断开方才会出现的,所以主动断开方是服务端?

答案是是的。在HTTP1.1协议中,有个Connection头,Connection有两个值,close和keep-alive,这个头就相当于客户端告诉服务端,服务端你执行完成请求之后,是关闭连接还是保持连接,保持连接就意味着在保持连接期间,只能由客户端主动断开连接。还有一个keep-alive的头,设置的值就代表了服务端保持连接保持多久。

HTTP默认的Connection值为close,那么就意味着关闭请求的一方几乎都会是由服务端这边发起的。那么这个服务端产生TIME_WAIT过多的情况就很正常了。

虽然HTTP默认Connection值为close,但是现在的浏览器发送请求的时候一般都会设置Connection为keep-alive了。所以,也有人说,现在没有必要通过调整参数来使TIME_WAIT降低了。

短连接与长连接

对于频繁请求资源的客户来说,较适用长连接。但连接数最好进行限制,防止建立太多连接拖累服务端。一般浏览器对一个网站的连接是有限制的几个,所以网站会将资源部署在多个域名上以实现浏览器同时请求。

短/长连接应当在TCP连接的范畴中来讨论。有人常说HTTP的短连接和长连接如何如何,但是HTTP只是一个应用层协议,又是无状态的,最终实质性的保持连接还是得靠传输层,即TCP。

举个例子,NginX作为代理的一种常见配置方式是在NginX与客户端之间的连接使用长连接,NginX与后端服务器之间的连接使用短连接。

keep-alive

我们使用浏览器的开发者工具查看网络请求和响应信息时经常在HTTP请求头部看到Connection:keep-alive,一般的浏览器都会带着个头去请求数据,假如有特殊需求可以用Connection:close断开。HTTP头部的Connection也不一定就被客户端或服务端老老实实地遵循,毕竟各有各的考虑,尤其是在HTTP/1.0这还只是个实验性的功能,而在HTTP/1.1默认长连接于是没有对长连接做特殊的规定。

长连接也不能无限期地长,服务端有可能在头部放Keep-Alive,其中timeout等于一个值来规定保持连接的秒数,还可以用max来规定多少次请求后断开。如果没有说明怎么断开,主动发起四次握手也可以实现连接的断开。

算法性能测试?压力测试

互斥锁信号量

信号量与普通整型变量的区别:

①信号量(semaphore)是非负整型变量,除了初始化之外,它只能通过两个标准原子操作:wait(semap),signal(semap);来进行访问;

信号量与互斥锁之间的区别:

1.互斥量用于线程的互斥,信号线用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源2.互斥量值只能为0/1,信号量值可以为非负整数。也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量是,也可以完成一个资源的互斥访问。3.互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。

项目的系统架构图》》》》

功能的流程图》》》

软件架构方面硬件架构方面

服务器卡顿怎么排查:

free,top,iostat等等看看CPU,内存,网络情况

而异步则是相反,*调用*在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。

典型的异步编程模型比如Node.js

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

linux进程间通讯的几种方式的特点和优缺点,和适用场合

由于不同的进程运行在各自不同的内存空间中.一方对于变量的修改另一方是无法感知的.因此.进程之间的信息传递不可能通过变量或其它数据结构直接进行,只能通过进程间通信来完成。

管道(pipe):

管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。有名管道(namedpipe):

有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

信号量(semophore):

信号量是一个计数器,可以用来控制多个进程对共享资源的访问。

它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作

为进程间以及同一进程内不同线程之间的同步手段。#消息队列(messagequeue):消息队列是由消息的链表,存放在内核中并由消息队列标识

符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

信号(sinal):

信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

#共享内存(sharedmemory):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的IPC

方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,

如信号量,配合使用,来实现进

程间的同步和通信。

#套接字(socket):

套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

管道的主要局限性正体现在它的特点上:

只支持单向数据流;

只能用于具有亲缘关系的进程之间;没有名字;

管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);

管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等;

管道通信(PIPE)两个进程利用管道进行通信时.发送信息的进程称为写进程.接收信息的进程称为读进程。管道通信方式的中间介质就是文件.通常称这种文件为管道文件.它就像管道一样将一个写进程和一个读进程连接在一起,实现两个进程之间的通信。写进程通过写入端(发送端)往管道文件中写入信息;读进程通过读出端(接收端)从管道文件中读取信息。两个进程协调不断地进行写和读,便会构成双方通过管道传递信息的流水线。利用系统调用PIPE()可以创建一个无名管道文件,通常称为无名管道或PIPE;利用系统调用MKNOD()可以创建一个有名管道文件.通常称为有名管道或FIFO。无名管道是一种非永久性的管道通信机构.当它访问的进程全部终止时,它也将随之被撤消。无名管道只能用在具有家族联系的进程之间。有名管道可以长期存在于系统之中.而且提供给任意关系的进程使用,但是使用不当容易导致出错.所以操作系统将命名管道的管理权交由系统来加以控制管道文件被创建后,可以通过系统调用WRITE()和READ()来实现对管道的读写操作;通信完后,可用CLOSE()将管道文件关闭。

消息缓冲通信(MESSAGE)多个独立的进程之间可以通过消息缓冲机制来相互通信.这种通信的实现是以消息缓冲区为中间介质.通信双方的发送和接收操作均以消息为单位。在存储器中,消息缓冲区被组织成队列,通常称之为消息队列。消息队列一旦创建后即可由多进程共享.发送消息的进程可以在任意时刻发送任意个消息到指定的消息队列上,并检查是否有接收进程在等待它所发送的消息。若有则唤醒它:而接收消息的进程可以在需要消息的时候到指定的消息队列上获取消息.如果消息还没有到来.则转入睡眠状态等待。

共享内存通信(SHAREDMEMORY)针对消息缓冲需要占用CPU进行消息复制的缺点.OS提供了一种进程间直接进行数据交换的通信方式一共享内存顾名思义.这种通信方式允许多个进程在外部通信协议或同步,互斥机制的支持下使用同一个内存段(作为中间介质)进行通信.它是一种最有效的数据通信方式,其特点是没有中间环节.直接将共享的内存页面通过附接.映射到相互通信的进程各自的虚拟地址空间中.从而使多个进程可以直接访问同一个物理内存页面.如同访问自己的私有空间一样(但实质上不是私有的而是共享的)。因此这种进程间通信方式是在同一个计算机系统中的诸进程间实现通信的最快捷的方法.而它的局限性也在于此.即共享内存的诸进程必须共处同一个计算机系统.有物理内存可以共享才行。

三种方式的特点(优缺点):

1.无名管道简单方便.但局限于单向通信的工作方式.并且只能在创建它的进程及其子孙进程之间实现管道的共享:有名管道虽然可以提供给任意关系的进程使用.但是由于其长期存在于系统之中,使用不当容易出错。

3.共享内存针对消息缓冲的缺点改而利用内存缓冲区直接交换信息,无须复制,快捷、信息量大是其优点。但是共享内存的通信方式是通过将共享的内存缓冲区直接附加到进程的虚拟地址空间中来实现的.因此,这些进程之间的读写操作的同步问题操作系统无法实现。必须由各进程利用其他同步工具解决。另外,由于内存实体存在于计算机系统中.所以只能由处于同一个计算机系统中的诸进程共享。不方便网络通信。

MySQL实现了四种通信协议

1.TCP/IP协议,通常我们通过来连接MySQL,各种主要编程语言都是根据这个协议实现了连接模块

2.UnixSocket协议,这个通常我们登入MySQL服务器中使用这个协议,因为要使用这个协议连接MySQL需要一个物理文件,文件的存放位置在配置文件中有定义,值得一提的是,这是所有协议中最高效的一个。

1、介绍Java中所有的集合;

2、ArrayList和LinkedList的增删改查的效率问题;

3、Set,Map和List集合共同继承什么类;

4、介绍同步锁,使用情景,都可以再哪里使用;

5、假如有两个线程,一个线程A,一个线程B都会访问一个加锁方法,可能存在并发情况,但是线程B访问频繁,线程A访问次数很少,问如何优化。(我第一次遇到这个问题,说不会,然后面试官说有了解过重度锁和轻度锁吗)

6、介绍下线程和进程的关系;

7、进程间都有哪些通信方式;

8、讲一下AIDL;

9、了解Handler机制吗,讲解下;

10、MessageQueue的工作原理;

11、假如有一个一秒和三秒延迟的消息在MessageQueue里面,请问在加入一个两秒延迟的消息插入顺序是怎样的;

12、假如消息队列里有3个消息,分别是延迟1秒,延迟2秒,延迟3秒,如果1秒的已经消耗了500毫秒,这时延迟2秒的会变成1.5秒,并且在插入一个2秒的会排在1.5秒之后,请讲解下这个原理;

13、这个算法,给纸和笔,有一个整数,转换为二进制,请找出所有的1的数量;

14、你觉得Java是完全面相对象的语言吗?

面向对象是一种约束规范,并不是绝对的,比如静态属性比如int这些

15、讲解下你对抽象,多态的理解;

16、讲解下安卓的四大组建,对哪个比较熟;

17、Activity的生命周期;

18、那你讲下,Activity中的onCreate方法里调用finish方法后,会调用哪些方法;

21、讲解下自己的项目,同时还现场去我的GitHub里看我的开源项目;

22、有什么想问我的,我问了我的缺点和优势;

介绍自己。

Tcp和udp的区别。分别适用于哪些场景。

三次握手四次挥手。。是否可以两次握手,为何要四次挥手。

Get和post区别。

Java有没有多继承,接口和抽象类区别。jvm理解

jre和jdk的区别

数据库四个范式的区别。在设计数据库的时候如何考量。

为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库,必须满足一定的范式。

在实际开发中最为常见的设计范式有三个:

第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。

第一范式的合理遵循需要根据系统的实际需求来定。比如某些数据库系统中需要用到“地址”这个属性,本来直接将“地址”属性设计成一个数据库表的字段就行。但是如果系统经常会访问“地址”属性中的“城市”部分,那么就非要将“地址”这个属性重新拆分为省份、城市、详细地址等多个部分进行存储,这样在对地址中某一部分操作的时候将非常方便。这样设计才算满足了数据库的第一范式,如下表所示。

上表所示的用户信息遵循了第一范式的要求,这样在对用户使用城市进行分类的时候就非常方便,也提高了数据库的性能。

比如要设计一个订单信息表,因为订单中可能会有多种商品,所以要将订单编号和商品编号作为数据库表的联合主键,如下表所示。

订单信息表

而如果把这个订单信息表进行拆分,把商品信息分离到另一个表中,把订单项目表也分离到另一个表中,就非常完美了。如下所示。

这样设计,在很大程度上减小了数据库的冗余。如果要获取订单的商品信息,使用商品编号到商品信息表中查询即可。

比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。如下面这两个表所示的设计就是一个满足第三范式的数据库表。

这样在查询订单信息的时候,就可以使用客户编号来引用客户信息表中的记录,也不必在订单信息表中多次输入客户信息的内容,减小了数据冗余。

第一范式:具有原子性

第二范式:主键列与非主键列遵循完全函数依赖关系

第三范式:非主键列之间没有传递函数依赖关系

大家都说标准规范是重要的指导方针并且也这么做着,但是把它当作石头上的一块标记来记着(死记硬背)还是会带来麻烦的。以下11点是我在数据库设计时最优先考虑的规则。

◆规则1:弄清楚将要开发的应用程序是什么性质的(OLTP还是OPAP)?

当你要开始设计一个数据库的时候,你应该首先要分析出你为之设计的应用程序是什么类型的,它是“事务处理型”(Transactional)的还是“分析型”(Analytical)的?你会发现许多开发人员采用标准化做法去设计数据库,而不考虑目标程序是什么类型的,这样做出来的程序很快就会陷入性能、客户定制化的问题当中。正如前面所说的,这里有两种应用程序类型,“基于事务处理”和“基于分析”,下面让我们来了解一下这两种类型究竟说的是什么意思。

那么换句话说,如果你认为插入、更新、删除数据这些操作在你的程序中更为突出的话,那就设计一个规范化的表否则的话就去创建一个扁平的、不规范化的数据库结构。

以下这个简单的图表显示了像左边Names和Address这样的简单规范化的表,怎么通过应用不规范化结构来创建一个扁平的表结构。

◆规则2:将你的数据按照逻辑意义分成不同的块,让事情做起来更简单

这个规则其实就是“三范式”中的第一范式。违反这条规则的一个标志就是,你的查询使用了很多字符串解析函数

例如substring、charindex等等。若真如此,那就需要应用这条规则了。

比如你看到的下面图片上有一个有学生名字的表,如果你想要查询学生名字中包含“Koirala”,但不包含“Harisingh”的记录,你可以想象一下你将会得到什么样的结果。

所以更好的做法是将这个字段拆分为更深层次的逻辑分块,以便我们的表数据写起来更干净,以及优化查询。

◆规则3:不要过度使用“规则2”

开发者都是一群很可爱的生物。如果你告诉他们这是一条解决问题的正路,他们就会一直这么做下去,做到过了头导致了一些不必要的后果。这也可以应用于我们刚刚在前面提到的规则2。当你考虑字段分解时,先暂停一下,并且问问你自己是否真的需要这么做。正如所说的,分解应该是要符合逻辑的。

◆规则4:把重复、不统一的数据当成你最大的敌人来对待

集中那些重复的数据然后重构它们。我个人更加担心的是这些重复数据带来的混乱而不是它们占用了多少磁盘空间。

例如下面这个图表,你可以看到"5thStandard"和"Fifthstandard"是一样的意思,它们是重复数据。现在你可能会说是由于那些录入者录入了这些重复的数据或者是差劲的验证程序没有拦住,让这些重复的数据进入到了你的系统。现在,如果你想导出一份将原本在用户眼里十分困惑的数据显示为不同实体数据的报告,该怎么做呢?

解决方法之一是将这些数据完整地移到另外一个主表,然后通过外键引用过来。在下面这个图表中你可以看到我们是如何创建一个名为“Standards”(课程级别)的主表,然后同样地使用简单的外键连接过去。

◆规则5:当心被分隔符分割的数据,它们违反了“字段不可再分”

前面的规则2即“第一范式”说的是避免“重复组”。下面这个图表作为其中的一个例子解释了“重复组”是什么样子的。如果你仔细的观察syllabus(课程)这个字段,会发现在这一个字段里实在是填充了太多的数据了。像这些字段就被称为“重复组”了。如果我们又得必须使用这些数据,那么这些查询将会十分复杂并且我也怀疑这些查询会有性能问题。

这些被塞满了分隔符的数据列需要特别注意,并且一个较好的办法是将这些字段移到另外一个表中,使用外键连接过去,同样地以便于更好的管理。

那么,让我们现在就应用规则2(第一范式)“避免重复组”吧。你可以看到上面这个图表,我创建了一个单独的syllabus(课程)表,然后使用“多对多”关系将它与subject(科目)表关联起来。

通过这个方法,主表(student表)的syllabus(课程)字段就不再有重复数据和分隔符了。

◆规则6:当心那些仅仅部分依赖主键的列

留心注意那些仅仅部分依赖主键的列。例如上面这个图表,我们可以看到这个表的主键是RollNo.+Standard。现在请仔细观察syllabus字段,可以看到syllabus(课程)字段仅仅关联(依赖)Standard(课程级别)字段而不是直接地关联(依赖)某个学生(RollNo.字段)。

Syllabus(课程)字段关联的是学生正在学习的哪个课程级别(Standard字段)而不是直接关联到学生本身。那如果明天我们要更新教学大纲(课程)的话还要痛苦地为每个同学也修改一下,这明显是不符合逻辑的(不正常的做法)。更有意义的做法是将这些字段从这个表移到另外一个表,然后将它们与Standard(课程级别)表关联起来。

你可以看到我们是如何移动syllabus(课程)字段并且同样地附上Standard表。

这条规则只不过是“三范式”里的“第二范式”:“所有字段都必须完整地依赖主键而不是部分依赖”。

◆规则7:仔细地选择派生列

如果你正在开发一个OLTP型的应用程序,那强制不去使用派生字段会是一个很好的思路,除非有迫切的性能要求,比如经常需要求和、计算的OLAP程序,为了性能,这些派生字段就有必要存在了。

通过上面的这个图表,你可以看到Average字段是如何依赖Marks和Subjects字段的。这也是冗余的一种形式。因此对于这样的由其他字段得到的字段,需要思考一下它们是否真的有必要存在。

这个规则也被称为“三范式”里的第三条:“不应该有依赖于非主键的列”。我的个人看法是不要盲目地运用这条规则,应该要看实际情况,冗余数据并不总是坏的。如果冗余数据是计算出来的,看看实际情况再来决定是否应用这第三范式。

◆规则8:如果性能是关键,不要固执地去避免冗余

不要把“避免冗余”当作是一条绝对的规则去遵循。如果对性能有迫切的需求,考虑一下打破常规。常规情况下你需要做多个表的连接操作,而在非常规的情况下这样的多表连接是会大大地降低性能的。

◆规则9:多维数据是各种不同数据的聚合

OLAP项目主要是解决多维数据问题。比如你可以看看下面这个图表,你会想拿到每个国家、每个顾客、每段时期的销售额情况。简单的说你正在看的销售额数据包含了三个维度的交叉。

为这种情况做一个实际的设计是一个更好的办法。简单的说,你可以创建一个简单的主要销售表,它包含了销售额字段,通过外键将其他所有不同维度的表连接起来。

◆规则10:将那些具有“名值表”特点的表统一起来设计

很多次我都遇到过这种“名值表”。“名值表”意味着它有一些键,这些键被其他数据关联着。比如下面这个图表,你可以看到我们有Currency(货币型)和Country(国家)这两张表。如果你仔细观察你会发现实际上这些表都只有键和值。

对于这种表,创建一个主要的表,通过一个Type(类型)字段来区分不同的数据将会更有意义。

◆规则11:无限分级结构的数据,引用自己的主键作为外键

我们会经常碰到一些无限父子分级结构的数据(树形结构?)。例如考虑一个多级销售方案的情况,一个销售人员之下可以有多个销售人员。注意到都是“销售人员”。也就是说数据本身都是一种。但是层级不同。这时候我们可以引用自己的主键作为外键来表达这种层级关系,从而达成目的。

详细设计数据库步骤。

二、关于java虚拟机1、垃圾回收算法,为什么要分代处理2、GC停顿原因,如何降低停顿3、JVM如何调优,参数怎么调4、如何使用工具分析jvm状态5、类加载机制6、什么是java虚拟机,对jvm的理解7、jvm内存模型,各个区的作用8、堆的作用9、JVM调试工具10、堆和栈的区别11、内存溢出了怎么办12、什么时候会栈溢出

三、关于java后台1、介绍Spring的IOC和AOP,分别是如何实现的(反射机制和动态代理)2、redis如何处理分布式服务器并发造成的不一致,如果数据库不提供隔离呢?3、解释MySQL索引、b树,为啥不用平衡二叉树或红黑树(磁盘与内存的存储方式不同)4、Spring的bean加载机制,bean生成的具体步骤5、IOC的注入方式(set注入、构造方法注入)6、Spring何时创建applicationContext(web.xml中使用listener)7、listener是监听哪个事件8、SpringMVC的具体流程9、Spring的特性,SpringMVC中控制器的名字及其配置10、Spring用到哪些设计模式?11、controller怎么处理的请求

六、关于Linux1、epoll、epollh和select的区别2、Linux下的一些指令,怎么查看进程,按照内存大小,CPU占用排序等

八、设计模式1、单例模式2、生产者模式、消费者模式

文件A100亿记录,文件B100万记录,找出A中不在B中的记录

13、数据库两个表关联的方式

14、数据库表关联的内部算法

15、数据库锁的实现

16、数据库表里有100万条数据,想要删除80万条数据,但是因为锁的原因,删除很慢,现在想要快速删除怎么办

网易内推

一面(项目)

1.项目的架构,怎么实现的

2.会不会javaweb的知识

4.测试人员需要的能力

5.有没有比较熟的b/s架构

二面(测试思维)(未通过)

1.写代码:找出一组数中最大的数

2.所接触到的测试的内容

3.对淘宝的搜索栏进行测试(1.宝贝,店铺,天猫选项;2.搜索栏;3.搜索按钮)

4.与他人相比,你的优势(此处最好答热情和测试行业大趋势和前景)

中兴

58面试

一面(基础)1.介绍一下项目2.流行的加密算法(Lz是信息安全方向的硕士,很多面试官都会稍微考考信息安全的问题,考察一下对专业知识的了解)3.写代码(找出数组中不重复的数)4.写上述代码的测试用例5.SQL(写语句,top,count,groupby,orderby,select)6.linux(cd..,cd-,mkdir,vi,netstat)7.java(忘记了)8.网络(get和post的区别,七层分别是什么,应用层的协议)9.测试(测试一个系统的性能,具体不记得了)二面(基础)1.自我介绍2.写代码(单例模式)3.SQL(索引,多表查找)4.数组和链表的区别5.hash的用处6.怎么解决hash冲突7.linux就不问了8.DNS劫持的原理三面(HR)1.自我介绍2.有什么符合软件测试岗位的优势3.用三个词形容自己4.遇到过什么困难5.有没有考虑过离乡背井的艰难

14.java中的集合的底层实现二面(算法)1.三人三鬼安全运过河(不详述)2.两个同样大小的罐子,一个装盐,一个装糖。首先从盐罐舀一勺盐到糖罐,再将糖罐中的混合物搅拌均匀,再从糖罐舀一勺混合物到盐罐,问,最后是糖罐的盐多还是盐罐的糖多(用公式计算的还不行,要一下就能得出结果的想法)3.写代码(判断字符串数组是否可以收尾相连成环路)4.写代码(从int型数组中找出和连续子串,要求和最大)5.测一个存储系统B(系统B有上级系统A,系统B中有1T存储容量,每天0点定时更新,还有分布式的缓存……)三面(现场+交叉面)(未通过)1.自我介绍2.什么是有效的沟通3.对一个功能进行压力测试4.滴滴抢单给出了新思路(大概是就用抢单之后会等10s,对抢单的司机进行最优匹配),让设计整个架构,并列出测试点5.对滴滴的了解

2.对于每个知识点,最好说出自己的理解,不要直接背书上的1234点。就拿java中问的比较常见“抽象类和接口的区别”举例。如果你回答1.java中抽象类只能单继承,但可以实现多个接口,2.抽象类中可以有方法的定义与实现,接口中方法不能实现………………这样的回答大家都会,所以如果说完上述这些,再加入一点自己实际学习中的理解会更好。比如:通常,我会把phone定义为一个抽象类,它是各种不同手机类的一个抽象。然而有的手机具有指纹解锁的功能,有的手机具有防水防尘的功能,对于这些附加的功能,我会把它们分别定义成不同的接口。当我需要这个功能的时候,在具体的类中再去实现这个功能。这样会更加符合面向对象中高内聚低耦合的特点…………就是这类似这样的回答,会更加突出你学习中的思考过程。

4.面试官都很不错,有的时候会给你一些提示和引导,所以放轻松,太紧张只会思路混乱;

1、HTTP请求的过程,越清楚越好(我从dns解析到TCP三次握手,四次挥手,还有后台请求逻辑讲了一遍)

2、Java线程池ThreadPoolEcecutor参数,基本参数,使用场景

3、HashMap、HashTable、CurrentHashMap的区别及场景,说一下你的理解。HashMap的负载因子,干啥用的。

4、ArrayList与LinkedList的区别及使用场景,有没有ArrayList增删效率比LinkedList高的场景。ArrayList底层采用什么实现数据的拷贝。

5、MySQL的ACID讲一下,延伸到隔离级别

6、JMM讲一下,volite关键字及使用场景。

7、JVM的内存布局以及垃圾回收原理及过程讲一下。讲一下CMS垃圾收集器垃圾回收的流程。以及CMS的缺点(忘了。。)

8、智力题(聊着聊着突然来个),两个杯子,一个有3升水,一个有5升水,请问如何倒出4升水。。(我回答说,使两者水平面一致。。。。一看到题,就这样啊。。但其答案不是我回答的这。。)

9、手写二叉树的中序遍历与层序遍历

10、手写二分查找(很基础)

11、最后还聊了一下项目,聊一下难点。

12、最后就是你有什么要问的。1、表现2、你们那边主要用那些java技术3、如果过,啥时通知下一面结果。

THE END
1.为什么不能经常算命在中国传统文化中,八字算命是一种通过分析个人出生年月日时(即“生辰八字”)来预测命运、性格和未来趋势的方法,它源于古代的阴阳五行学说,经过数千年的发展,形成了一套复杂的理论体系,尽管许多人对八字算命抱有浓厚的兴趣,但频繁进行此类占卜却可能带来一些不利影响,本文将探讨为何不宜经常算命,并提供相关背景信息以https://www.zhouyibj.com/show-53812.html
2.八字命理师是否会利用八字害人声誉风险:如果八字命理学家使用八字伤害他人,他们的声誉可能会受到损害,导致客户和收入的丧失。 法律后果:在某些国家或地区,使用八字害人可能构成犯罪行为,并受到法律制裁。 结论: 虽然八字命理学家有可能使用八字来伤害他人,但这并不常见。大多数八字命理学家都是道德专业人士,不会使用八字来伤害他人。在选择八字命理http://www.juicychina.net/view/103909
3.人防(民防)知识竞赛试题及参考答案养、激发干部热情为目标开展人防(民防)知识竞赛。本资 料的编制以习近平新时代中国特色社会主义思想和关于人 民防空重要讲话精神为指导,以实施四川人防“2510”战略 发展为目标,四川省《人防(民防)知识竞赛试题及参考答 案》是专门针对此次知识竞赛活动编制的学习资料,其目的 http://rfb.cngy.gov.cn/news/detail/20190610162528569.html
4.三年级公共安全教育课这样的行为正确吗?可能造成什么样的后果呢? 自行车轻巧灵活,是外出理想的交通工具,不少同学都想学骑自行车。当你学会骑车、兴冲冲地骑车上马路时,可千万要注意骑车安全啊! 读一读: 案例:小学生亮亮(11岁)骑自行车上学,当骑到工业大道,准备横过马路时,不避让本车道内的车辆,在一辆大货车行驶临近时横穿马路,被大货http://hyxx.mhedu.sh.cn/wmjw/sxjysssszcs/hsdy/242460.htm
5.iOS开发计算文字所占宽度iphone如何计算字数程序不需要编译,程序在运行时才翻译成机器语言,每执 行一次都要翻译一次。 2. 优缺点 解释型语言执行效率较低,且不能脱离解释器运行,但它的跨平台型比较容易,只需提供特定解释器即可。 3. 举例 python、JS都是解释型语言。 二、强制类型转换 & 隐式类型转换 https://blog.51cto.com/u_16099224/8988024
6.网上算命会被偷走运气吗,算命算一次命薄一分另外,现在很多年轻人把算命当做是一种无足轻重的行为,甚至是一种娱乐的活动。这就会造成一种典型的情况,算来算去:好的不准,坏的奇准。殊不知这正是:命越算越薄的征兆! 三、命越算越薄 在算命界流传着这样一句话“命越算越薄”,很多人想算命的人都会问,这是真的吗?一个命理师在其职业生涯中必然会碰到https://m.lbzuo.com/vip_doc/28744584.html
7.病人家属咨询抗抑郁药的解答答:氟西汀造成厌食,当然不适合厌食症,可是你的孩子当前不厌食,故可以使用。 14是否卡马西平引起多形性红斑,吃拉莫三嗪也 会过敏? 答:有可能,这叫交叉过敏,虽然不一定发生,但我是不敢尝试了。 15.使用氟西汀过程中要注意什么副反应? 答:烦躁、失眠 https://www.chunyuyisheng.com/pc/topic/451568/
8.卦算多了会怎么样命真的会越算越薄吗每个人对于自己的命运如何都是会有或多或少的好奇心的,所以一直以来也是有不少人会去算卦,算命,想知道自己的未来会是怎样的,而且还不止一次去算。那么卦算多了会怎么样?命真的会越算越薄吗?今天我们一起来看看! 卦算多了会怎么样 有说法认为卦算多了会运势变的越来越不好,但这样的说法是很难说的准的,https://www.qiyuange.com/zhouyi/46572.html
9.初一第一学期期考政治复习提纲(通用6篇)答:利用联想后果法来抵制这种诱惑,并婉言谢绝朋友,提高自制力,劝朋友也不要去。 (2)对于游戏的诱惑,你怎么样去看待? 答:适度的、有节制的游戏并不是坏事。适度的游戏可以放松和调节自己;可以开发智力;可以锻炼眼耳 手脑并用的能力。但是如果沉迷于游戏会对身心健康造成损害;会影响学习成绩;还会诱发违纪违法甚至犯https://www.360wenmi.com/f/filel1bj6k5i.html
10.心理诊疗室:那些隐藏在热点事件背后的心理动因很多可怜的妻子像刘女性一样,抱有对丈夫改邪归正的幻想。也出于对家庭和孩子的责任心,并没有离开那个对自己家暴的男人,相信了他们的认错。不成想,下一次拳头打过来,只会越来越密集。 中国应用法学研究所研究员陈敏曾在写《中国女性反家庭暴力报告》的时候,发现一个令人震惊的数据:给家暴妇女支持小组打电话求助的https://story.hao.360.cn/topic/LNrZQkrnNHC7Qw
11.孩子?堕胎(墮胎須知)Inducedabortion我宁願放弃自己的生命,也不願再做一次堕胎的手術! <哈本医师的悔改> 阿爾諾德.哈本医师,曾经是一家計畫生育堕胎诊所的负责人。 阿爾諾德.哈本医师:【从前我会做堕胎手術,是因为我误认为:胚胎要到二十週大,当你可以听到他的心跳,怀孕的婦女可以感觉到他在动的时候,才算是真正的婴儿。 我不清楚我是从何处得到https://duotai.wordpress.com/tag/%E5%AD%A9%E5%AD%90/
12.头条文章无忧无虑的童年不会再回来,无法触摸。 什么叫人生,什么叫人生如梦, 因为有的人生很远,像天涯一样远。 你了解了天涯的远,才能知道人生的远。 遥不可及的远。 十三个字,没有一个废字。 用词精确。 人生如梦,天涯很远,都让人愁。 这句话的情感就是一个愁字, https://m.weibo.cn/ttarticle/p/show?id=2309404805745026662545
13.软考高级——信息系统项目管理师(第4版)思维导图模板信息(Information)是物质、能量及其属性的标示的集合,是确定性的增加。它以物质介质为载体,传递和反映世界各种事物存在方式、运动状态等的表征。信息不是物质,也不是能力,它以一种普遍形式,表达物质运动规律,在客观世界中大量存在、产生和传递。 信息的特征与质量 https://www.processon.com/view/654c455f8f11b40fe56ece43
14.对话张一鸣:精英们一直试图提高大众的精神追求,但社会整体从未张一鸣:不能容忍对系统的长期损害。我定义过三层廉洁失效给公司造成的损害:第一层是直接利益损失;第二层是这些决策带来的不良后果;第三层是廉洁风气变坏后,团队向心力的丧失。而第三层是我绝对不能容忍的。 《财经》:头条在管理架构和原则上有什么特点? https://www.tmtpost.com/2545031.html