java校招面试常见题型

1.加密和解密

·     1.Base64

·       严格来说Base64并不是一种加密/解密算法,而是一种编码方式。Base64不生成密钥,通过Base64编码后的密文就可以直接“翻译”为明文,但是可以通过向明文中添加混淆字符来达到加密的效果。

·     2.DES

·       DES是一种基于56位密钥的对称算法,1976年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),随后在国际上广泛流传开来。现在DES已经不是一种安全的加密算法,已被公开破解,现在DES已经被高级加密标准(AES)所代替。

·     3.3DES

·       3DES是DES的一种派生算法,主要提升了DES的一些实用所需的安全性。

·     4.AES

·       AES是现在对称加密算法中最流行的算法之一。

2.多线程,线程安全(synchronized)

·     新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

·     就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

·     运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

·     阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

o   1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

o   2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

o   3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

·     死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

·     sleep和wait的区别

o   1、每个对象都有一个锁来控制同步访问,Synchronized关键字可以和对象的锁交互,来实现同步方法或同步块。执行sleep()方法后正在执行的线程主动让出CPU(然后CPU就可以去执行其他任务),在sleep指定时间后CPU再回到该线程继续往下执行(注意:sleep方法只让出了CPU,而并不会释放同步资源锁!!!);wait()方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。(注意:notify的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说notify只是让之前调用wait的线程有权利重新参与线程的调度);

o   2、sleep()方法可以在任何地方使用;wait()方法则只能在同步方法或同步块中使用;

o   3、sleep()是线程类(Thread)的方法,调用会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间自动恢复;wait()是Object的方法,调用会放弃对象锁,进入等待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才会进入锁池,再次获得对象锁才会进入运行状态;

o    

·     线程创建的三种基本形式:

o   1. 继承Thread类,重写该类的run()方法;

o   2. 实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。

o   3. 使用Callable和Future接口创建线程。具体是创建Callable接口的实现类,并实现call()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程。

o   非线程安全是指多线程操作同一个对象可能会出现问题。

o   而线程安全则是多线程操作同一个对象不会有问题。

§  Vector  HashTable  StringBuffer  statck enumeration是线程安全的.

§  ArrayList、 LinkedList、HashMap、StringBuilder 是非线程安全的。

·     

2+、关于死锁

·     产生死锁的原因主要是:

o   1) 因为系统资源不足。

o   2) 进程运行推进的顺序不合适。

o   3) 资源分配不当等。    

·     导致死锁的4个必要条件:

o   1、互斥条件。一次只有一个进程可以使用一个资源。其他进程不能访问已分配给其他进程的资源。

o   2、请求保持条件。当一个进程等待其他进程时,继续占有已经分配的资源。

o   3、不可剥夺条件。不能强行抢占进程已占有的资源。

o   4、循环等待条件。存在一个封闭的进程链,使得每个进程至少占有此链中下一个进程所需要的一个资源。

·     死锁预防策略

o   是试图设计一种系统来排除发生死锁的可能性,方法分为两类:间接的死锁预防方法(防止前面三个列出的三个必要条件中的任何一个的发生);直接的死锁的预防方法(防止循环等待的发生)。

·     死锁避免策略

o   银行家算法:首先需要定义状态和安全状态的概念。系统的状态是当前给进程分配的资源情况。因此,状态包含两个向量Resource(系统中每种资源的总量)和Available(未分配给进程的每种资源的总量)及两个矩阵Claim(表示进程对资源的需求)和Allocation(表示当前分配给进程的资源)。安全状态是指至少有一个资源分配序列不会导致死锁。当进程请求一组资源时,假设同意该请求,从而改变了系统的状态,然后确定其结果是否还处于安全状态。如果是,同意这个请求;如果不是,阻塞该进程知道同意该请求后系统状态仍然是安全的。

15、synchronized

·     Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

o   一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

o   二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

o   三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

o    四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

o   五、以上规则对其它对象锁同样适用.

·     它包括两种用法:synchronized 方法和 synchronized 块。 

·      1. synchronized 方法:

o   通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:  
public synchronized void accessVal(int newVal);  
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。  
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。  
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。  

·     2. synchronized 块:

o   通过 synchronized关键字来声明synchronized 块。语法如下:  
synchronized(syncObject) {  
//允许访问控制的代码  
}  
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。

·     A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。

·     B.每个对象只有一个锁(lock)与之相关联。

·     C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

o   1. 把synchronized当作函数修饰符时,示例代码如下:

o   Public synchronized void methodAAA()

o   {

o   //….

o   }

o   这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。

o   2.同步块,示例代码如下:

o   public void method3(SomeObject so)

o   {

o       synchronized(so)

o       { 
       //….. 
    }

o   }

o   这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:

o   class Foo implements Runnable

o   {

o           private byte[] lock = new byte[0]; // 特殊的instance变量

o           Public void methodA() 
        {

o              synchronized(lock) { //… }

o           }

o           //…..

o   }

3、常用的设计模式

·      1.单例模式(singleton)

o     如果一个类始终只能创建一个实例,则这个类被称为单例类,这种模式就被称为单例模式。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。

§  1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。

o   单例模式主要有如下两个优势:

§  1) 减少创建Java实例所带来的系统开销

§  2)便于系统跟踪单个Java实例的生命周期、实例状态等。

o   double-check双重检查。

§  public class Singleton    {    
    private static final Singleton singleton = null;    
    private Singleton(){    
    }    
    public static Singleton getInstance() {    
        if (singleton== null){    
            synchronized (Singleton.class) {    
                if (singleton== null){    
                    singleton= new Singleton();    
                }    
            }    
        }    
        return singleton;    
    }    
}  

o   更简单的

§  public class Singleton  {    
    private static final Singleton singleton = new Singleton();
    private Singleton(){    
    }    
    public static Singleton getInstance(){    
        return singleton;    
    }    
}  

·     2.简单工厂模式(StaticFactory Method)

o   简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

o   使用简单工厂模式的优势:让对象的调用者和对象创建过程分离,当对象调用者需要对象时,直接向工厂请求即可。从而避免了对象的调用者与对象的实现类以硬编码方式耦合,以提高系统的可维护性、可扩展性。工厂模式也有一个小小的缺陷:当产品修改时,工厂类也要做相应的修改。

o   优点:工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。

o    缺点:由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;

o    

·     3.工厂方法(FactoryMethod)和抽象工厂(Abstract Factory)

4、Java中HashMap的工作原理

·     1. 什么时候会使用HashMap?他有什么特点?

o   是基于Map接口的实现,存储键值对时,它可以接收null的键值,是非同步的,HashMap存储着Entry(hash, key, value, next)对象。

·     2. 你知道HashMap的工作原理吗?

o   通过hash的方法,通过put和get存储和获取对象。存储对象时,我们将K/V传给put方法时,它调用hashCode计算hash从而得到bucket位置,进一步存储,HashMap会根据当前bucket的占用情况自动调整容量(超过Load Factor(负载因子)则resize为原来的2倍)。获取对象时,我们将K传给get,它调用hashCode计算hash从而得到bucket位置,并进一步调用equals()方法确定键值对。如果发生碰撞的时候,Hashmap通过链表将产生碰撞冲突的元素组织起来,在Java 8中,如果一个bucket中碰撞冲突的元素超过某个限制(默认是8),则使用红黑树来替换链表,从而提高速度。

·     3. 你知道get和put的原理吗?equals()和hashCode()的都有什么作用?

o   当使用HashMap的put方法的时候,有两个问题要解决:

§  1、长度为16的数组中,元素存储在哪个位置 
2、如果key出现hash冲突,如何解决

o   第一个问题,HashMap 是使用下面的算法来计算元素的存放位置的。

§  int hash = hash(key); 

§  int i = indexFor(hash, table.length);

§  首先先hash,之后结合数组的长度进行一个&操作得到得到数组的下标。

o   第二个问题 则利用Entry类的next变量来实现链表,把最新的元素放到链表头,旧的数据则被最新的元素的next变量引用着。 
举个例子,假设元素Entry<"1","1">通过hash算法算出存到下标为0的位置上,后面又添加一个Entry<"2","2">, 
假设Entry<"2","2">通过hash算法算出也需要存到下标为0的数组中,那么此时链表是下面这个样子的:

§  Entry<”2”,”2”> –>Entry<”1”,”1”>

§  也即是说,当key出现hash冲突的时候,链表中的第一个元素都是后面最新添加进来的那个,之前的则被next变量引用着。虽然这里是插入的动作,但是由于使用了链表,所以无需像数组的插入那样,进行数组拷贝。

o   get方法

§  这个操作的原理就比较简单,只需要根据key的hashcode算出元素在数组中的下标,之后遍历Entry对象链表,直到找到元素为止。

§  int hash = (key == null) ? 0 : hash(key);

§  for(Entry<K,V> e =table[indexFor(hash,table.length)];e != null;e = e.next){    

§  Object k;   

§  if (e.hash == hash && ((k = e.key)== key || (key != null &&key.equals(k))))         return e; }

§  这里有两个注意点: 
1、这里利用key的hashcode方法和equals方法,所以在使用HashMap的时候,如果使用对象作为key,最好覆写key的hashcode和equals方法 ,不然可能出put到HashMap的时候成功了,但是get的时候却没有找到数据 
2、如果key hash冲突太多,会造成链表过长,在链表中查找元素的时候,会比较慢

·     4. 你知道hash的实现吗?为什么要这样实现?

o   在Java 1.8的实现中,是通过hashCode()的高16位异或低16位实现的:(h =k.hashCode()) ^ (h >>> 16),主要是从速度、功效、质量来考虑的,这么做可以在bucket的n比较小的时候,也能保证考虑到高低bit都参与到hash的计算中,同时不会有太大的开销。

·     5. 如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?

o   如果超过了负载因子(默认0.75),则会重新resize一个原来长度两倍的HashMap,并且重新调用hash方法。

5、Oracle:

·      oracle中不存在引擎的概念,数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。

·     OLTP 系统强调数据库内存效率,强调内存各种指标的命令率,强调绑定变量,强调并发操作;

·     OLAP 系统则强调数据分析,强调SQL执行市场,强调磁盘I/O,强调分区等。

·     Mysql和oracle的一些区别

o   1. Oracle是大型数据库而Mysql是中小型数据库,Oracle市场占有率达40%,Mysql只有20%左右,同时Mysql是开源的而Oracle价格非常高。

o   2. Oracle支持大并发,大访问量,是OLTP最好的工具。

o   3. 安装所用的空间差别也是很大的,Mysql安装完后才152M而Oracle有3G左右,且使用的时候Oracle占用特别大的内存空间和其他机器性能。

o   一、并发性
并发性是OLTP数据库最重要的特性,但并发涉及到资源的获取、共享与锁定。
mysql:
mysql以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他session无法更新此表中的数据。
虽然InnoDB引擎的表可以用行级锁,但这个行级锁的机制依赖于表的索引,如果表没有索引,或者sql语句没有使用索引,那么仍然使用表级锁。
oracle:
oracle使用行级锁,对资源锁定的粒度要小很多,只是锁定sql需要的资源,并且加锁是在数据库中的数据行上,不依赖与索引。所以oracle对并发性的支持要好很多。
二、一致性
oracle支持serializable的隔离级别,可以实现最高级别的读一致性。每个session提交后其他session才能看到提交的更改。oracle通过在undo表空间中构造多版本数据块来实现读一致性,
每个session查询时,如果对应的数据块发生变化,oracle会在undo表空间中为这个session构造它查询时的旧的数据块。
mysql没有类似oracle的构造多版本数据块的机制,只支持readcommited的隔离级别。一个session读取数据时,其他session不能更改数据,但可以在表最后插入数据。
session更新数据时,要加上排它锁,其他session无法访问数据。
三、事务
oracle很早就完全支持事务。
mysql在innodb存储引擎的行级锁的情况下才支持事务。
四、数据持久性
oracle
保证提交的数据均可恢复,因为oracle把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,
如果出现数据库或主机异常重启,重启后oracle可以考联机在线日志恢复客户提交的数据。
mysql:
默认提交sql语句,但如果更新过程中出现db或主机重启的问题,也许会丢失数据。
五、提交方式
oracle默认不自动提交,需要用户手动提交。
mysql默认是自动提交。
六、逻辑备份
oracle逻辑备份时不锁定数据,且备份的数据是一致的。
mysql逻辑备份时要锁定数据,才能保证备份的数据是一致的,影响业务正常的dml使用。
七、热备份
oracle有成熟的热备工具rman,热备时,不影响用户使用数据库。即使备份的数据库不一致,也可以在恢复时通过归档日志和联机重做日志进行一致的回复。
mysql:
myisam的引擎,用mysql自带的mysqlhostcopy热备时,需要给表加读锁,影响dml操作。
innodb的引擎,它会备份innodb的表和索引,但是不会备份.frm文件。用ibbackup备份时,会有一个日志文件记录备份期间的数据变化,因此可以不用锁表,不影响其他用户使用数据库。但此工具是收费的。
innobackup是结合ibbackup使用的一个脚本,他会协助对.frm文件的备份。
八、sql语句的扩展和灵活性
mysql对sql语句有很多非常实用而方便的扩展,比如limit功能,insert可以一次插入多行数据,select某些管理数据可以不加from。
oracle在这方面感觉更加稳重传统一些。
九、复制
oracle:既有推或拉式的传统数据复制,也有dataguard的双机或多机容灾机制,主库出现问题是,可以自动切换备库到主库,但配置管理较复杂。
mysql:复制服务器配置简单,但主库出问题时,丛库有可能丢失一定的数据。且需要手工切换丛库到主库。
十、性能诊断
oracle有各种成熟的性能诊断调优工具,能实现很多自动分析、诊断功能。比如awr、addm、sqltrace、tkproof等
mysql的诊断调优方法较少,主要有慢查询日志。
十一、权限与安全
mysql的用户与主机有关,感觉没有什么意义,另外更容易被仿冒主机及ip有可乘之机。
oracle的权限与安全概念比较传统,中规中矩。
十二、分区表和分区索引
oracle的分区表和分区索引功能很成熟,可以提高用户访问db的体验。
mysql的分区表还不太成熟稳定。
十三、管理工具
oracle有多种成熟的命令行、图形界面、web管理工具,还有很多第三方的管理工具,管理极其方便高效。
mysql管理工具较少,在linux下的管理工具的安装有时要安装额外的包(phpmyadmin, etc),有一定复杂性。

7、数据库连接池

·     官方定义:

o   数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。
个人理解:创建数据库连接是一个很耗时的操作,也容易对数据库造成安全隐患。所以,在程序初始化的时候,集中创建多个数据库连接,并把他们集中管理,供程序使用,可以保证较快的数据库读写速度,还更加安全可靠。

·      数据库连接池的运行机制

o   (1)  程序初始化时创建连接池
(2) 使用时向连接池申请可用连接
(3) 使用完毕,将连接返还给连接池
(4) 程序退出时,断开所有连接,并释放资源

8、java并发编程,核心理论

·     一、共享性

o     数据共享性是线程安全的主要原因之一。如果所有的数据只是在线程内有效,那就不存在线程安全性问题,这也是我们在编程的时候经常不需要考虑线程安全的主要原因之一。但是,在多线程编程中,数据共享是不可避免的。最典型的场景是数据库中的数据,为了保证数据的一致性,我们通常需要共享同一个数据库中数据,即使是在主从的情况下,访问的也同一份数据,主从只是为了访问的效率和数据安全,而对同一份数据做的副本。我们现在,通过一个简单的示例来演示多线程下共享数据导致的问题:

§  public class ShareData {

§      public static int count = 0;

§      public static void main(String[] args) {

§          final ShareData data = new ShareData();

§          for (int i = 0; i < 10; i++) {

§              new Thread(new Runnable() {

§                  @Override

§                  public void run() {

§                      try {

§                     //进入的时候暂停1毫秒,增加并发问题出现的几率

§                          Thread.sleep(1);

§                      } catch (InterruptedException e) {

§                          e.printStackTrace();

§                      }

§                      for (int j = 0; j < 100; j++) {

§                          data.addCount();

§                      }

§                      System.out.print(count + " ");

§                  }

§              }).start();

§          }

§          try {

§              //主程序暂停3秒,以保证上面的程序执行完成

§              Thread.sleep(3000);

§          } catch (InterruptedException e) {

§              e.printStackTrace();

§          }

§          System.out.println("count=" + count);

§      }

§      public void addCount() {

§          count++;

§      }

§  }

§   

·     二、互斥性

o     资源互斥是指同时只允许一个访问者对其进行访问,具有唯一性和排它性。我们通常允许多个线程同时对数据进行读操作,但同一时间内只允许一个线程对数据进行写操作。所以我们通常将锁分为共享锁和排它锁,也叫做读锁和写锁。如果资源不具有互斥性,即使是共享资源,我们也不需要担心线程安全。例如,对于不可变的数据共享,所有线程都只能对其进行读操作,所以不用考虑线程安全问题。但是对共享数据的写操作,一般就需要保证互斥性,上述例子中就是因为没有保证互斥性才导致数据的修改产生问题。Java 中提供多种机制来保证互斥性,最简单的方式是使用Synchronized。现在我们在上面程序中加上Synchronized再执行:

o   public class ShareData {

o       public static int count = 0 ;

o       public static void main(String[] args) {

o           final ShareData data = new ShareData();

o           for (int i = 0; i < 10; i++) {

o               new Thread(new Runnable() {

o                   @Override

o                   public void run() {

o                       try {

o                           //进入的时候暂停1毫秒,增加并发问题出现的几率

o                           Thread.sleep(1);

o                       } catch (InterruptedException e) {

o                           e.printStackTrace();

o                       }

o                       for (int j = 0; j < 100; j++) {

o                           data.addCount();

o                       }

o                       System.out.print(count + " ");

o                   }

o               }).start();

o    

o           }

o           try {

o               //主程序暂停3秒,以保证上面的程序执行完成

o               Thread.sleep(3000);

o           } catch (InterruptedException e) {

o               e.printStackTrace();

o           }

o           System.out.println("count=" + count);

o       }

o       /**

o        * 增加 synchronized 关键字

o        */

o       public synchronized void addCount() {

o           count++;

o       }

o   }

o   现在再执行上述代码,会发现无论执行多少次,返回的最终结果都是1000。

·     三、原子性

o     原子性就是指对数据的操作是一个独立的、不可分割的整体。换句话说,就是一次操作,是一个连续不可中断的过程,数据不会执行到一半的时候被其他线程所修改。保证原子性的最简单方式是操作系统指令,就是说如果一次操作对应一条操作系统指令,这样肯定可以能保证原子性。但是很多操作不能通过一条指令就完成。例如,对long类型的运算,很多系统就需要分成多条指令分别对高位和低位进行操作才能完成。还比如,我们经常使用的整数 i++ 的操作,其实需要分成三个步骤:(1)读取整数 i 的值;(2)对 i 进行加一操作;(3)将结果写回内存。这个过程在多线程下就可能出现如下现象:

·     

o   这也是代码段一执行的结果为什么不正确的原因。对于这种组合操作,要保证原子性,最常见的方式是加锁,如Java中的Synchronized或Lock都可以实现,代码段二就是通过Synchronized实现的。除了锁以外,还有一种方式就是CAS(Compare And Swap),即修改数据之前先比较与之前读取到的值是否一致,如果一致,则进行修改,如果不一致则重新执行,这也是乐观锁的实现原理。不过CAS在某些场景下不一定有效,比如另一线程先修改了某个值,然后再改回原来值,这种情况下,CAS是无法判断的。

·     四、可见性

o    要理解可见性,需要先对JVM的内存模型有一定的了解,JVM的内存模型与操作系统类似,如图所示:

·       

o   从这个图中我们可以看出,每个线程都有一个自己的工作内存(相当于CPU高级缓冲区,这么做的目的还是在于进一步缩小存储系统与CPU之间速度的差异,提高性能),对于共享变量,线程每次读取的是工作内存中共享变量的副本,写入的时候也直接修改工作内存中副本的值,然后在某个时间点上再将工作内存与主内存中的值进行同步。这样导致的问题是,如果线程1对某个变量进行了修改,线程2却有可能看不到线程1对共享变量所做的修改。

·     五、有序性

o   为了提高性能,编译器和处理器可能会对指令做重排序。重排序可以分为三种:

o   (1)编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。

o   (2)指令级并行的重排序。现代处理器采用了指令级并行技术(Instruction-LevelParallelism,ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
(3)内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

18、volatile关键字(原子性,可见性,有序性)

·     1.volatile关键字的两层语义

·     一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

o   1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

o   2)禁止进行指令重排序。

·     但是用volatile修饰之后就变得不一样了:

o   第一:使用volatile关键字会强制将修改的值立即写入主存;

o   第二:使用volatile关键字的话,当线程2进行修改时,会导致线程1的工作内存中缓存变量stop的缓存行无效(反映到硬件层的话,就是CPU的L1或者L2缓存中对应的缓存行无效);

o   第三:由于线程1的工作内存中缓存变量stop的缓存行无效,所以线程1再次读取变量stop的值时会去主存读取。

9、HashMap的原理

·     HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。”这里关键点在于指出,HashMap是在bucket中储存键对象和值对象,作为Map.Entry。

·     “当两个对象的hashcode相同会发生什么?” 

o   从这里开始,真正的困惑开始了,一些面试者会回答因为hashcode相同,所以两个对象是相等的,HashMap将会抛出异常,或者不会存储它们。然后面试官可能会提醒他们有equals()和hashCode()两个方法,并告诉他们两个对象就算hashcode相同,但是它们可能并不相等。一些面试者可能就此放弃,而另外一些还能继续挺进,他们回答“因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。”这个答案非常的合理,虽然有很多种处理碰撞的方法,这种方法是最简单的,也正是HashMap的处理方法。但故事还没有完结,面试官会继续问:

·     “如果两个键的hashcode相同,你如何获取值对象?” 

o   面试者会回答:当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,然后获取值对象。面试官提醒他如果有两个值对象储存在同一个bucket,他给出答案:将会遍历链表直到找到值对象。面试官会问因为你并没有值对象去比较,你是如何确定找到值对象的?除非面试者知道HashMap在链表中存储的是键值对,否则他们不可能回答出这一题。

o   其中一些记得这个重要知识点的面试者会说,找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。完美的答案!

10、红黑树

·     一、红黑树性质

·     1.每个结点要么是红的要么是黑的

·     2.根结点是黑的

·     3.每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的

·     4.如果一个结点是红的,那么它的两个儿子都是黑的

·     5.对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点

·     总结:平衡状态下红黑树要么单支黑-红,要么有两个子节点

·      二、 复杂度(O(logn))

·      三、结点插入

·      四、结点删除

·      五、应用场景

11、堆排序的原理

·     堆是一种特殊的树形数据结构,其每个节点都有一个值,通常提到的堆都是指一颗完全二叉树,根结点的值小于(或大于)两个子节点的值,同时,根节点的两个子树也分别是一个堆

·     它的基本思想是,将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余的 n-1 个序列重新构造成一个堆,这样就会得到 n 个元素中次大的值。如此反复执行,便能得到一个有序序列了。

·     堆排序的实现需要解决的两个关键问题: 
(1)将一个无序序列构成一个堆。 
(2)输出堆顶元素后,调整剩余元素成为一个新堆。

o  publicclassHeapSort {     /**      * 构建大顶堆      */   

o    publicstaticvoidadjustHeap(int[] a, int i, int len){       

o     int temp,j;       

o     temp = a[i];       

o     for (j = 2 * i; j< len; j *= 2) {

o  // 沿关键字较大的孩子结点向下筛选               

o        if (j < len&& a[j] < a[j + 1])             

o                ++j; // j为关键字中较大记录的下标         

o        if (temp>= a[j])            

o                break;           

o        a[i] = a[j];          

o        i =j;       

o     }     

o      a[i] =temp;   

o   }     

o  publicstaticvoidheapSort(int[] a) {        

o        int i;        

o        for (i = a.length / 2 - 1; i>= 0; i--) {// 构建一个大顶堆               

o             adjustHeap(a, i, a.length - 1);       

o        }       

o        for (i = a.length - 1; i>= 0; i--) {

o         // 将堆顶记录和当前未经排序子序列的最后一个记录交换          

o            int temp = a[0];          

o            a[0] = a[i];            

o            a[i] = temp;           

o            adjustHeap(a, 0, i - 1);

o         // 将a中前i-1个记录重新调整为大顶堆      

o         } 

o     }   

o    publicstaticvoidmain(String[] args) {      

o           int a[] = { 51, 46, 20, 18, 65, 97, 82, 30, 77, 50 };     

o           heapSort(a);        

o           System.out.println(Arrays.toString(a));    

o     }

o  }

12、 Object类有哪些方法

·      1.clone方法

o   保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。

·      2.getClass方法

o   final方法,获得运行时类型。

·      3.toString方法

o   该方法用得比较多,一般子类都有覆盖。

·      4.finalize方法

o   该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。

·      5.equals方法

o   该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。

·      6.hashCode方法

o   该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。

o   一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash-Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。

·      7.wait方法

o   wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。

o   调用该方法后当前线程进入睡眠状态,直到以下事件发生。

§  (1)其他线程调用了该对象的notify方法。

§  (2)其他线程调用了该对象的notifyAll方法。

§  (3)其他线程调用了interrupt中断该线程。

§  (4)时间间隔到了。

o   此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。

·      8.notify方法

o   该方法唤醒在该对象上等待的某个线程。

·      9.notifyAll方法

o   该方法唤醒在该对象上等待的所有线程。

13、Forward和redirect的区别

·     forward方式:request.getRequestDispatcher("/somePage.jsp").forward(request,response);     

·      redirect方式:response.sendRedirect("/somePage.jsp");

·     forward是服务器内部重定向,程序收到请求后重新定向到另一个程序,客户机并不知道;redirect则是服务器收到请求后发送一个状态头给客户,客户将再请求一次,这里多了两次网络通信的来往。当然forward也有缺点,就是forward的页面的路径如果是相对路径就会有些问题了。forward会将request state ,bean等等信息带往下一个jsp。redirect是送到client端后再一次request,所以资料不被保留.使用forward你就可以用getAttribute()来取的前一个jsp所放入的bean等等资料。

·     1.从地址栏显示来说

·       forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.

·       redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.所以redirect等于客户端向服务器端发出两次request,同时也接受两次response。

·     2.从数据共享来说

·       forward:转发页面和转发到的页面可以共享request里面的数据.
  redirect:不能共享数据.

·       redirect不仅可以重定向到当前应用程序的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源.forward,方法只能在同一个Web应用程序内的资源之间转发请求.forward 是服务器内部的一种操作.redirect 是服务器通知客户端,让客户端重新发起请求.所以,你可以说 redirect是一种间接的请求, 但是你不能说"一个请求是属于forward还是redirect "
3.从运用地方来说

·       forward:一般用于用户登陆的时候,根据角色转发到相应的模块.

·       redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.

·     4.从效率来说
  forward:高.
  redirect:低.

14、Spring框架

·     Spring是一个开源框架,主要优势是分层架构,分层架构允许你选择使用哪个组件,同时为J2EE应用程序开发提供集成的构架。

·     Spring两个最有趣的模块:Spring面向方面编程(AOP)和控制反转(IOC)容器。

·     Spring 框架的 7 个模块:

七模块解析

·     核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

·     Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。

·     Spring AOP(面向方面编程):通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

·      Spring DAO(数据访问对象):JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

·     Spring ORM(对象关系映射):Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

·     Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

·     Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText和 POI。

Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境(Web 或 EJB)、独立应用程序、测试环境之间重用。

·     IOC(控制反转)和 AOP(面向方面编程)

o   控制反转模式(也称作依赖性介入)的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器(在 Spring 框架中是 IOC 容器) 负责将这些联系在一起。

o   面向方面的编程,即 AOP,是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中。

o   AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中,可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上。当然,优势就是 Java 类不需要知道日志服务的存在,也不需要考虑相关的代码。所以,用 SpringAOP 编写的应用程序代码是松散耦合的。

16、在什么情况下使用线程池? 
     1.单个任务处理的时间比较短 
     2.将需处理的任务的数量大 
     使用线程池的好处: 
      1.减少在创建和销毁线程上所花的时间以及系统资源的开销 
        2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”  过度切换”。

19、建立索引的优缺点:

·     优点

o   通过建立索引可以极大地提高在数据库中获取所需信息的速度,同时还能提高服务器处理相关搜索请求的效率,从这个方面来看它具有以下优点[1]  :

o   在设计数据库时,通过创建一个惟一的索引,能够在索引和信息之间形成一对一的映射式的对应关系,增加数据的惟一性特点。

o   能提高数据的搜索及检索速度,符合数据库建立的初衷。

o   能够加快表与表之间的连接速度,这对于提高数据的参考完整性方面具有重要作用。

o   在信息检索过程中,若使用分组及排序子句进行时,通过建立索引能有效的减少检索过程中所需的分组及排序时间,提高检索效率。

o   建立索引之后,在信息查询过程中可以使用优化隐藏器,这对于提高整个信息检索系统的性能具有重要意义。

·     缺点

o   虽然索引的建立在提高检索效率方面具有诸多积极的作用,但还是存在下列缺点[1]  :

o   在数据库建立过程中,需花费较多的时间去建立并维护索引,特别是随着数据总量的增加,所花费的时间将不断递增。

o   在数据库中创建的索引需要占用一定的物理存储空间,这其中就包括数据表所占的数据空间以及所创建的每一个索引所占用的物理空间,如果有必要建立起聚簇索引,所占用的空间还将进一步的增加

o   在对表中的数据进行修改时,例如对其进行增加、删除或者是修改操作时,索引还需要进行动态的维护,这给数据库的维护速度带来了一定的麻烦。

20、面向对象的五个基本原则和三个基本元素

·     三个基本元素:

·     1. 封装: 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
2. 继承: 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。 
3. 多态: 多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

·     C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。

·     
五个基本原则:
单一职责原则(Single-Resposibility Principle):一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。
开放封闭原则(Open-Closed principle):软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。
Liskov替换原则(Liskov-Substituion Principle):子类必须能够替换其基类。这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。
依赖倒置原则(Dependecy-Inversion Principle):依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。
接口隔离原则(Interface-Segregation Principle):使用多个小的专门的接口,而不要使用一个大的总接口。

1、TCP/IP协议

·     OSI分层 (7层):物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
TCP/IP分层(4层):网络接口层、 网际层、运输层、 应用层。
五层协议 (5层):物理层、数据链路层、网络层、运输层、 应用层。
每一层的协议如下:
物理层:RJ45、CLOCK、IEEE802.3 (中继器,集线器)
数据链路:PPP、FR、HDLC、VLAN、MAC (网桥,交换机)
网络层:IP、ICMP、ARP、RARP、OSPF、IPX、RIP、IGRP、(路由器)
传输层:TCP、UDP、SPX
会话层:NFS、SQL、NETBIOS、RPC
表示层:JPEG、MPEG、ASII
应用层:FTP、DNS、Telnet、SMTP、HTTP、WWW、NFS
每一层的作用如下:
物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)
数据链路层:将比特组装成帧和点到点的传递(帧Frame)
网络层:负责数据包从源到宿的传递和网际互连(包PackeT)
传输层:提供端到端的可靠报文传递和错误恢复(段Segment)
会话层:建立、管理和终止会话(会话协议数据单元SPDU)
表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU)
应用层:允许访问OSI环境的手段(应用协议数据单元APDU)

2、IP的分类

·     A类地址:以0开头,  第一个字节范围:1~127(1.0.0.0 - 127.255.255.255);

·     B类地址:以10开头, 第一个字节范围:128~191(128.0.0.0 - 191.255.255.255);

·     C类地址:以110开头,第一个字节范围:192~223(192.0.0.0 -223.255.255.255);

·     D类地址:以1110开头,第一个字节范围:224~239(224.0.0.0 - 239.255.255.255);(作为多播使用)

·     E类地址:保留

·     其中A、B、C是基本类,D、E类作为多播和保留使用。

·     以下是留用的内部私有地址:

·     A类10.0.0.0--10.255.255.255

·     B类172.16.0.0--172.31.255.255

·     C类192.168.0.0--192.168.255.255

·     IP地址与子网掩码相与得到网络号:

·     ip: 192.168.2.110 &Submask : 255.255.255.0

·     网络号   :192.168.2  .0

·     注:

·     主机号,全为0的是网络号(例如:192.168.2.0),主机号全为1的为广播地址(192.168.2.255)

·     TCP端口,即传输控制协议端口,需要在客户端和服务器之间建立连接,这样可以提供可靠的数据传输。常见的包括FTP服务的21端口,Telnet服务的23端口,SMTP服务的25端口,以及HTTP服务的80端口,HTTPS服务端口号为443等等

3、TCP三次握手与四次挥手

·     三次握手:

o   第一次握手:客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。

·     四次挥手

o   与建立连接的“三次握手”类似,断开一个TCP连接则需要“四次握手”。
第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可以接受数据。
第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。
第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。

4、在浏览器中输入www.baidu.com后执行的全部过程

·      1、客户端浏览器通过DNS解析到www.baidu.com 的IP地址220.181.27.48,通过这个IP地址找到客户端到服务器的路径。客户端浏览器发起一个HTTP会话到220.181.27.48,然后通过TCP进行封装数据包,输入到网络层。
2、在客户端的传输层,把HTTP会话请求分成报文段,添加源和目的端口,如服务器使用80端口监听客户端的请求,客户端由系统随机选择一个端口如5000,与服务器进行交换,服务器把相应的请求返回给客户端的5000端口。然后使用IP层的IP地址查找目的端。
3、客户端的网络层不用关心应用层或者传输层的东西,主要做的是通过查找路由表确定如何到达服务器,期间可能经过多个路由器,这些都是由路由器来完成的工作,我不作过多的描述,无非就是通过查找路由表决定通过那个路径到达服务器。
4、客户端的链路层,包通过链路层发送到路由器,通过邻居协议查找给定IP地址的MAC地址,然后发送ARP请求查找目的地址,如果得到回应后就可以使用ARP的请求应答交换的IP数据包现在就可以传输了,然后发送IP数据包到达服务器的地址。

o    

5、TCP和UDP的区别

·      TCP提供面向连接的、可靠的数据流传输,而UDP提供的是非面向连接的、不可靠的数据流传输。
TCP
传输单位称为TCP报文段,UDP传输单位称为用户数据报。
TCP
注重数据安全性,UDP数据传输快,因为不需要连接等待,少了许多操作,但是其安全性却一般。
TCP
对应的协议和UDP对应的协议
TCP
对应的协议:
(1) FTP:定义了文件传输协议,使用21端口。
(2) Telnet:一种用于远程登陆的端口,使用23端口,用户可以以自己的身份远程连接到计算机上,可提供基于DOS模式下的通信服务。
(3) SMTP:邮件传送协议,用于发送邮件。服务器开放的是25号端口。
(4) POP3:它是和SMTP对应,POP3用于接收邮件。POP3协议所用的是110端口。
(5)HTTP:是从Web服务器传输超文本到本地浏览器的传送协议。
UDP
对应的协议:
(1) DNS:用于域名解析服务,将域名地址转换为IP地址。DNS用的是53号端口。
(2) SNMP:简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
(3) TFTP(TrivalFile Transfer Protocal),简单文件传输协议,该协议在熟知端口69上使用UDP服务。

6、多进程之间的通信方式

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

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

·     # 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

·     # 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

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

·     # 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

·     # 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

 

 

 

发布了1 篇原创文章 · 获赞 1 · 访问量 2594

猜你喜欢

转载自blog.csdn.net/weixin_37750901/article/details/78431804