Java面试题(持续日更)

1、Java面向对象都有哪些特性以及你对这些特性的了解。

继承:继承是从已有的类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类),得到继承的是子类。

封装:把数据和操作数据的方法绑定起来,对数据的访问只能通过定义的接口。我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程端口。

多态性:多态是指允许不同子类型的对象对同一消息作出不同的响应。简单的来说就是用同样的对象调用同样的方法,但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态可以解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但对于A系统来说都是透明的。方法重载(overload)实现的是编译时的多态性,而方法重写(override)实现的是运行时的多态性。

三大特性:继承、封装、多态

抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

2、访问权限修饰符public、private、protected,以及不写(默认)时的区别

3、StringBuffer与StringBuilder的区别

       StringBuffer安全(多线程)、StringBuilder是线程不安全(单线程)

       StringBuffer和StringBuilder类都表示内容可以被修改的字符串,StringBuilder是线程不安全的,运行效率高,如果一个字符串变量是在方法里面定义,这种情况只可能有一个线程访问它,不存在不安全的因素了,则用StringBuilder。如果要在类里面定义成员变量,并且这个类的实例对象会在多线程环境下使用,那么最好用StringBuffer。

4、序列化和反序列化

       把对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为对象的过程称为对象的反序列化。

  对象的序列化主要有两种用途:

  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

扫描二维码关注公众号,回复: 8631707 查看本文章

  2) 在网络上传送对象的字节序列。

5、Collection 和 Collections的区别

       Collection是集合类的上级接口,继承与他的接口主要有Set 和List。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。

Collections 是一个包装类。是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作,不能实例化。

6、什么时候应用带参构造函数?

       当需要对对象进行一次性的初始化时,可使用带参的构造函数。父类拥有带参的构造时,子类继承父类,子类需编写带参数构造函数,并调用父类构造函数。

7、内部类的二个好处是?

内部类的第一个好处是:隐藏你不想让别人知道的操作,也即封装性。

内部类的第二个好处谁:每一个内部类对象可以访问创建它的外部类对象的内容,甚至包、括私有变量!

8、方法重载与重写的区别?

重写(Override):重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

重载(overload):重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载。

重写方法名和参数都一样,重载方法名一样,参数不一定一样。

9、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?

        可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。

10、说说&和&&的区别。

        &和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。

        &&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,例如,对于if(str!= null&& !str.equals(s))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常。If(x==33 &++y>0) y会增长,If(x==33 && ++y>0)不会增长

        &还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0x31 & 0x0f的结果为0x01。

11、是否可以从一个static方法内部发出对非static方法的调用?

        不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。

12、Integer与int的区别

        int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。

        例如:要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。

13、List和 Map区别?

        一个是存储单列数据的集合,另一个是存储键和值这样的双列数据的集合,List中存储的数据是有顺序,并且允许重复;Map中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。

14、String s = new String("xyz");创建了几个StringObject?是否可以继承String类?

        两个或一个都有可能,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。NewString每写一遍,就创建一个新的对象,它使用常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,那么这里就不会创建”xyz”了,直接从缓冲区拿,这时创建了一个StringObject;但如果以前没有用过"xyz",那么此时就会创建一个对象并放入缓冲区,这种情况它创建两个对象。至于String类是否继承,答案是否定的,因为String默认final修饰,是不可继承的。

15、error和Exception有什么区别?

Error类和Exception类的父类都是throwable类,Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。Exception类表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。

16能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象?

我们可以做强制转换,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,所以,如果强制转化,int 类型的高 24 位将会被丢弃,因为byte 类型的范围是从 -128 到 127。

17、a.hashCode() 有什么用?与 a.equals(b) 有什么关系?

hashCode() 方法对应对象整型的 hash 值。它常用于基于 hash 的集合类,如 Hashtable、HashMap、LinkedHashMap等等。它与 equals() 方法关系特别紧密。根据 Java 规范,两个使用 equal() 方法来判断相等的对象,必须具有相同的 hash code。

18、GC是什么?为什么要有GC?

        GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

19、是否可以继承String

不可以,String是final类

20、break和continue的区别?

break和continue都是用来控制循环的语句,break用于完全结束一个循环,跳出循环体执行循环后面的语句。continue用于跳出本次循环,执行下次循环。

21、ArrayList 和 LinkedList 有什么区别?

ArrayList和LinkedList都实现了List接口,有以下的不同点:

1、ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。

2、相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。

3、LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

22、Java 中会存在内存泄漏吗,请简单描述。

理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生。例如hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露

23、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行,在return前还是后?

会执行,在方法返回调用者前执行。在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,就会返回修改后的值

24、List、Set、Map是否继承自Collection接口?

List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。

25、Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?

sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复。wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。

26、线程的sleep()方法和yield()方法有什么区别?

① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;

④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。

27、编写多线程程序有几种实现方式?

一种是继承Thread类;另一种是实现Runnable接口。两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用Runnable接口更为灵活。

28、synchronized关键字的用法?

synchronized关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问,可以用synchronized(对象) { … }定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符。

29、事务的ACID是指什么?

- 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
- 一致性(Consistent):事务结束后系统状态是一致的;
- 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
- 持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

30、获得一个类的类对象有哪些方式?

- 方法1:类型.class,例如:String.class
- 方法2:对象.getClass(),例如:”hello”.getClass()

- 方法3:Class.forName(),例如:Class.forName(“java.lang.String”)

31、进程和线程的区别是什么?

(1)进程是运行中的程序,线程是进程的内部的一个执行序列

(2)进程是资源分配的单元,线程是执行行单元

(3)进程间切换代价大,线程间切换代价小

(4)进程拥有资源多,线程拥有资源少,多个线程共享进程的资源

这种题目,专业术语不好理解,采用形象一点的比喻更好,比如:开个QQ,开了一个进程;开了迅雷,开了一个进程。在QQ的这个进程里,传输文字开一个线程、传输语音开了一个线程、弹出对话框又开了一个线程。所以运行某个软件,相当于开了一个进程。在这个软件运行的过程里(在这个进程里),多个工作支撑的完成QQ的运行,那么这“多个工作”分别有一个线程。
所以一个进程管着多个线程。

32、什么是死锁(deadlock)?

是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去

33、数组和链表的区别?

数组是将元素在内存中连续存储;他的优点:因为数据是连续存储的,内存地址连续,所以查找数据效率高;缺点:在存储之前,我们需要申请一块连续的内存空间,并且在编译的时候就必须确定好他的空间大小,并且之后无法改变数组内存大小,可能会出现数组越界、浪费内存的情况。在改变数据个数,增加、插入、删除数据效率比较低。

链表是动态申请内存空间,不需要提前申请内存大小,只需要在用的时候申请就可以,根据需要动态的申请或者删除内存空间,比数组更加灵活。链表中数据在内存中可以在任意位置,通过应用来关联数据(指针)。

34、什么是单例、多例

单例:所谓单例模式,就是保证类在内存中只有一个对象。service和dao层的对象通常都是单例的, 之所以用单例,是因为没必要每个请求都新建一个对象,这样子既浪费CPU又浪费内存;

多例:指每个请求用一个新的对象来处理,比如action;  之所以用多例,是为了防止并发问题;即一个请求改变了对象的状态,此时对象又处理另一个请求,而之前请求对对象状态的改变导致了对象对另一个请求做了错误的处理;

用单例和多例的标准只有一个, 当对象含有可改变的状态时则多例,否则单例;  

35、单例模式之饿汉式、懒汉式

饿汉式:该模式在类被加载时就会实例化一个对象。具体代码如下:

public class Person {
    //饿汉式单例
    private static Person person = new Person();
    private Person(){}

    public static Person getInstance(){
    return person;
    }
}

该模式能简单快速的创建一个单例对象,而且是线程安全的(只在类加载时才会初始化,以后都不会)。但它有一个缺点,就是不管你要不要都会直接创建一个对象,会消耗一定的性能(当然很小很小,几乎可以忽略不计,所以这种模式在很多场合十分常用而且十分简单)

懒汉式:该模式只在你需要对象时才会生成单例对象(比如调用getInstance方法)

public class User {
    //懒汉式单例,只有在调用getInstance时才会实例化一个单例对象
    public static User user; 

    public static Integer key  = new Integer(4);  //作为一个锁 
    private User(){
    }
    public static User getInstance(){
    //先判断该user变量是否为空,入股为空,进入同步代码块,该步假设为step1
    if(user == null){    //step 1     //想象一下,如果不判断,那么每次访问这个方法不管该对象是否已经创建都要进入同步代码块,线程数一多,资源消耗也是非常巨大的。
    synchronized (key) {
    //由于可能多个线程都进入了step1,由于锁定机制,一个线程进入该代码块时,其他线程
    //仍在排队进入该代码块,如果不做判断,当前线程即使创造了实例,下一个线程也不知道,就会继续创建一个实例
        if(user==null){
        user = new User();
        }
    }
}
    return user;
    }
}

通过上面的锁机制同步代码块就可以写出线程安全的懒汉式单例

36、接口和抽象类的区别?

1. 抽象类可以有构造方法,接口中不能有构造方法。

2. 抽象类中可以有普通成员变量,接口中没有普通成员变量

3. 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

4. 抽象类中的抽象方法的访问类型可以是public,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

5. 抽象类中可以包含静态方法,接口中不能包含静态方法

6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

7. 一个类可以实现多个接口,但只能继承一个抽象类。

37、GET和POST请求的区别? 

①get请求用来从服务器上获得资源,而post是用来向服务器提交数据; 

②get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,并且两者使用"?"连接,而各个变量之间使用"&"连接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action所指向URL; 

③get传输的数据要受到URL长度限制(1024字节);而post可以传输大量的数据,上传文件通常要使用post方式; 

④使用get时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏感数据还是应用使用post; 

⑤get使用MIME类型application/x-www-form-urlencoded的URL编码(也叫百分号编码)文本的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是"%20"。

38、“==”和equals方法的区别?

==为比较两侧的对象是否同一对象,是用内存地址来比较的

equals是方法,默认是用内存地址比较,重写后,主要是用来比较两侧的对象的值是否相同,和equals方法中的实现有关

==可以两侧都为null,但equals左侧的引用指向的对象不能空,不然有NullPointerException

39、hashMap和hashtable的区别:

map是一个键值对的存储接口,Map有两个具体的实现类是HashMap和HashTable,

hashmap是非线程安全的,hashtable是线程安全的,所以hashmap的效率高于hashtable;

hashmap允许空值空键,table不许空值空键;

关于map的底层,是通过数组加链表的形式来进行存放的,比如我们要存放一会key , value,我们会根据key的hashcode()值与数组的长度进行取余,通过余数放入到对应的数组位置上,然后通过key取值得时候,我们也是通过传过来的key的hashcode()与数组长度取余,然后就能很快的找到我们存放的位子。但是这样会存在一个问题,就是余数会有重复的情况,我们就加上一个链表。通过key取到链表之后,我们就将链表进行循环,然后相比较来查询出相对应的值;

40、说说你对缓存的理解

通常情况下缓存是为了提高应用程序的性能,减少数据库的访问次数,缓存的存储介质可以内存或者硬盘,通常将数据存储在内存里,确切的说是jvm的内存中,缓存是基于Map这种思想构建的,以键值对的方式进行存取,之所以还可以将缓存的数据存储在硬盘中,是因为内存资源相当有限和宝贵,所以当内存资源不足的时候,就可以将其存储到硬盘中,虽然硬盘的存取速度比内存要慢,但是因为减少了网络通信量,所以还是提高程序的性能。缓存可以分为客户端缓存和服务器端缓存,所谓的客户端缓存通常指的是IE浏览器的缓存,服务器端缓存指的web服务器的缓存,通常可以通过第三方组件实现,如oscache或者redis

我们通常将那些频繁访问但是又不是经常改变的数据进行缓存。为了保证缓存数据的有效性,在数据发生改变的时候,我们要刷新缓存,避免脏数据的出现。刷新缓存的策略有两种,一种是定时刷新,一种手动刷新。

缓存的层次如下:jsp-->action-->service(通常放置在service)-->dao,

缓存越靠前对性能的提升越大,缓存的策略:(缓存空间不足需要进行清理的时候使用)

LRU:最近最少使用原则.(理解:存储书)           FIFO:先进先出的缓存策略.(理解:排队)

41、工厂模式

工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A(). 工厂模式也是用来创建实例对象的,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

类Sample为例,要创建Sample的实例对象:Sample sample=new Sample();

可是,实际情况是,通常我们都要在创建sample实例时做点初始化的工作,比如赋值 查询数据库等,首先,我们想到的是,可以使用Sample的构造函数,这样生成实例就写成:

Sample sample=new Sample(参数); 

但是,如果创建sample实例时所做的初始化工作不是象赋值这样简单的事,可能是很长一段代码,如果也写入构造函数中,那你的代码很难看了,而且很麻烦。这个时候你就可以采用工厂方法来封装这个问题。不能再用上面简单new Sample(参数)。还有,如果Sample有个继承如MySample, 按照面向接口编程,我们需要将Sample抽象成一个接口.现在Sample是接口,有两个子类MySample 和HisSample

Sample mysample=new MySample();

Sample hissample=new HisSample(); 

采用工厂封装:

public class Factory{
  public static Sample creator(int which){
  //getClass 产生Sample 一般可使用动态类装载装入类。
  if (which==1)
    return new SampleA();
  else if (which==2)
    return new SampleB();
  }
} 

那么在你的程序中,如果要实例化Sample时.就使用

Sample sampleA=Factory.creator(1); 

工厂模式分为:简单工厂模式(被称为静态模式)、工厂方法模式、抽象工厂模式

工厂模式核心本质:实例化对象,用工厂方法代替new;举例生产汽车,创建一个工厂接口类Factory(生产汽车),具体生产什么车,实现工厂接口,生产的时候 Factory car1 = new Car1();  Factory car2 = new Car2();

42、原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。(设计模式可以分为三大类,分别是创建型、结构型和行为型。)

 原型模式是一种比较简单的模式,也非常容易理解,实现一个接口,重写一个方法即完成了原型模式。在实际应用中,原型模式很少单独出现。经常与其他模式混用,他的原型类Prototype也常用抽象类来替代。使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

原型类:

public abstract class Prototype implements Cloneable{
    private String id;
    public Prototype(String id) {
        this.id = id;
    }
    public String getId() {
        return this.id;
    }
    public Prototype clone() throws CloneNotSupportedException {
        return (Prototype) super.clone();  
    }
}

具体原型实现类:

public class CreateProtype extends Prototype{   
    public CreateProtype(String id) {
        super(id);
    }
}

客户端代码:

public class JavaDemo {
    public static void main(String[] args) throws CloneNotSupportedException {       
        Prototype p1 = new CreateProtype("1");
        Prototype p2 = p1.clone();
        System.out.println(p1 == p2);
    }
}

输出结果为false,说明并不是传值引用 ,两个对象有自己的地址。

43、Java反射

反射就是可以将一个程序(类)在运行的时候获得该程序(类)的信息的机制,也就是获得在编译期不可能获得的类的信息,因为这些信息是保存在Class对象中的,而这个Class对象是在程序运行时动态加载的 
它 就是可以在程序运行的时候动态装载类,查看类的信息,生成对象,或操作生成对象。类在运行的时候,可以得到该类的信息,并且 可以动态的修改这些信息。class对象是在运行的时候产生的,通过class对象操作类的信息是在运行时进行的,当运行程序的时候,类加载器会加载真正需要的类,什么是真正需要的呢?就是该类真正起作用,如:有该类的对象实例,或该类调用了静态方法属性等 

实现反射的三种方式:

(1)Class.forName(“全限类名”).class

(2)对象.class

(3)Class <?> class = 类名.class

通过class对象获取类的方法、参数、属性

44、什么是事务控制?

事务控制就是将一系列操作当成一个不可拆分的逻辑单元,保证这些操作要么都成功,要么都失败。在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。事务有两种操作:提交,回滚

事务是恢复和并发控制的基本单位。事务应该具有4个属性:原子性、一致性、隔离性、持续性。这四个属性通常称为ACID特性。

原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的

隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

45、字节流与字符流的区别

stream结尾都是字节流,reader和writer结尾都是字符流,两者的区别就是读写的时候一个是按字节读写,一个是按字符。实际使用通常差不多。在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流。只是读写文件,和文件内容无关的,一般选择字节流。

字节流是最基本的,采用ASCII编码,所有的InputStream和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的,但实际中很多的数据是文本,又提出了字符流的概念,采用Unicode编码.它是按虚拟机的encode来处理,也就是要进行字符集的转化。

46、你对Ajax、jquery的理解?

AJAX 全称: 异步JavaScript及 XML。Ajax的核心是JavaScript中的XmlHttpRequest(XHR)。

使用ajax可以提高用户的体验度,进行异步数据传输从而提高性能。ajax不能跨域。所谓的不能跨域就是不能跨多个网站(多个域名),不能跨多个项目。可以通过jsonp来解决ajax跨域的问题,而jsonp的实质就是通过动态添加script标签来实现的。

Jquery是一个js框架,拥有跨浏览器的特性,可以兼容各种浏览器,可以使用它的append方法、remove方法、insertAfter方法操作文档对象、通过id选择器$("#id")以及类选择器$(".class")还有标签选择器$("标签名")可以选择DOM元素、通过fadeIn以及fadeOut制作淡入淡出的动画效果、通过bind来对指定元素绑定事件、通过$.get,$.post以及$.ajax发送ajax异步请求。

47、java中实现线程的方式

在java中实现线程有两种方式:继承Thread类,实现Runable接口,一个java main程序默认会开启两个线程一个是主线程,一个垃圾回收线程。建议使用runable接口,因为java是单继承。

线程不安全与安全:

多个线程访问同一个资源,导致结果和期望值不同,我们就说它是线程不安全的,反之我们就说它是 线程安全的。

多个线程访问同一个资源(这里的资源通常指的是全局变量或者静态变量),如果每次运行结果和单线程运行的结果是一样的,就是线程安全的。线程安全问题都是由全局变量及静态变量引起的。

若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

48、线程的状态

1、新建状态(New):新创建了一个线程对象。(继承Thread类,实现Runnable接口)

2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:(自身的sleep()方法或其他线程的join()方法)
  (一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
  (二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
  (三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

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

当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同),进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒(由于notify()只是唤醒一个线程,但我们由不能确定具体唤醒的是哪一个线程,也许我们需要唤醒的线程不能够被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后会进入锁池,等待获取锁标记。

49、解决线程安全的问题的方案:

(1)通过加锁(synchronized)的方式解决线程安全问题:synchronized 方法 、synchronized 块(同步代码块)

(2)避免使用全局变量

(3)使用ThreadLocal

50、Java线程池

线程池的作用:

线程池作用就是限制系统中执行线程的数量。

根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。

为什么要用线程池:

1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。

实例:

public class MyThread extends Thread {
    @Override
    publicvoid run() {
        System.out.println(Thread.currentThread().getName() + "正在执行。。。");
    }
}
publicclassTestSingleThreadExecutor {
    publicstaticvoid main(String[] args) {

        //创建一个可重用固定线程数的线程池
        ExecutorService pool = Executors. newSingleThreadExecutor();
        //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口

        Thread t1 = new MyThread();
        Thread t2 = new MyThread();
        Thread t3 = new MyThread();
        Thread t4 = new MyThread();
        Thread t5 = new MyThread();

        //将线程放入池中进行执行
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        pool.execute(t4);
        pool.execute(t5);

        //关闭线程池
        pool.shutdown();
    }
}
/*
pool-1-thread-1正在执行。。。

pool-1-thread-1正在执行。。。

pool-1-thread-1正在执行。。。

pool-1-thread-1正在执行。。。

pool-1-thread-1正在执行。。。
*/

 

发布了77 篇原创文章 · 获赞 19 · 访问量 4023

猜你喜欢

转载自blog.csdn.net/qq_41861558/article/details/103920556