java基础串理

java知识串理


在这里插入图片描述

一、集合

1. 集合

java工具类,用来存储任意数量的具有相同属性的对象。

2.作用

(1)在类的内部,对数据进行组织;
(2) 简单快速的搜索出大量的条目;
(3)有的集合接口,提供一系列的有序元素,并在有序列中可以快速的插入删除有关元素;
(4) 有的集合接口提供映射关系,通过关键字去查找唯一对应的对象。
(顺便提一句,集合和数组的区别:
集合的长度是可以改变的,但是数组的长度不能改变;
数组只能通过下标去访问元素,但是集合除此之外还可以通过任意类型查找所映射的具体对象。

在这里插入图片描述
集合框架可以分为两大类:Map和Collection,而collection又可以分为三大类:list,set,Queue;Map类可以分为三大类:HashMap,TreeMap,HashTable。
List可以分为:ArrayList,LinkedList,Vector。
Set可以分为:HashSet,TreeSet,LinkedHashSet。

3.下面我们详细介绍一下这些集合框架
3.1List接口的实现类

(1)ArrayList
基于数组实现,非线性安全,效率高,增删慢查找快。
(2)Vector
基于数组实现,线性安全,效率低,增删慢查找慢
(3)LinkedList
基于链表实现,增删快查找慢(双向链表)

3.2set接口实现类

(1)HashSet
底层数据结构由HashMap实现,线程不安全,使用时要重写equals(),HashCode()方法
(2)TreeSet
可以通过红黑树对set集合中的元素进行排序,线程不安全
(3)LinkedHashSet
由链表实现,按照元素插入的顺序进行排序

3.3Map接口的实现类

(1)HashMap
基于hash表和map接口实现,非线性安全,高效,支持null值和null健,同步的
(2)HashTable
线程安全,低效,不支持null值和null健,非同步的
(3)TreeMap
底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。

4.常见的面试题
4.1set,Map,List,接口存取元素时各有什么特点?

set接口存取元素时不允许增加重复的元素(equals()方法区分)。
Map接口存取元素时采用键值对的方式来存取。(key唯一,value可以不唯一)。
List接口用特定的索引来存取,可以有重复的元素。

4.2collection,set,map,list之间的联系和区别?

collection接口和map接口是同等级的,而set,list是collection接口的子接口。

4.3collections和collection有什么区别?

collection 是集合框架中的一个顶层接口,它有三个子接口 List,Set,Queue。
collections 是集合框架中的一个类,该类中的方法是静态的,提供的方法中有可以对list集合进行排序,二分查找等方法。

4.4什么是HashMap冲突?怎么处理?

HashMap冲突:也叫HashMap碰撞,就是不同元素进行计算后得到相同的存储地址。
解决方法:JDK7采用数组+链表方法(头插法)
JDK8采用数组+链表+红黑树方法处理(尾插法)

4.5 HashMap结构中,jdk1.7和jdk1.8的区别?

区别:jdk1.7采用头插法,即数组+链表的方法。 这种方法容易出现逆序 环形链表,容易出现死循环。而jdk1.8采用尾插法,即数组+链表+红黑树的方法,这种方法有效的避免逆序和环形链表产生的死循环。

4.6什么是红黑树?特点有哪些?

红黑树:节点是红色或黑色的平衡二叉树,通过颜色约束二叉树的平衡。
特点:每个节点只能是红色或黑色;根节点叶节点是黑色;如果一个节点是红色,那他的两个子节点是黑色;任意节点到每个叶子的的所有路径都包含相同数目的黑色节点。

二、泛型

1.泛型

“参数化类型”是指所有的操作数据的类型被指定为一个参数。

2.作用

(1)解决元素存储的安全性问题
(2)解决获取数据元素时,需要类型强转的问题。
泛型可以分为:泛型类,泛型接口,泛型方法

3.泛型类
class 类名称 <泛型标识:可以随便写任意标识号,标识指定的泛型的类型>{
  private 泛型标识 /*(成员变量类型)*/ var; 
  .....

  }
}
       

一个最普通的泛型类:

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;

    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }

    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}
//泛型的类型参数只能是类类型(包括自定义类),不能是简单类型
//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
Generic<Integer> genericInteger = new Generic<Integer>(123456);

//传入的实参类型需与泛型的类型参数类型相同,即为String.
Generic<String> genericString = new Generic<String>("key_vlaue");
Log.d("泛型测试","key is " + genericInteger.getKey());
Log.d("泛型测试","key is " + genericString.getKey());
12-27 09:20:04.432 13063-13063/? D/泛型测试: key is 123456
12-27 09:20:04.432 13063-13063/? D/泛型测试: key is key_vlaue
4.泛型接口
//定义一个泛型接口
public interface Generator<T> {
    public T next();
}
/**
 * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
 * 即:class FruitGenerator<T> implements Generator<T>{
 * 如果不声明泛型,如:class FruitGenerator implements Generator<T>,编译器会报错:"Unknown class"
 */
class FruitGenerator<T> implements Generator<T>{
    @Override
    public T next() {
        return null;
    }
}
/**
 * 传入泛型实参时:
 * 定义一个生产器实现这个接口,虽然我们只创建了一个泛型接口Generator<T>
 * 但是我们可以为T传入无数个实参,形成无数种类型的Generator接口。
 * 在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型
 * 即:Generator<T>,public T next();中的的T都要替换成传入的String类型。
 */
public class FruitGenerator implements Generator<String> {

    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}
5.泛型方法
/**
 * 泛型方法的基本介绍
 * @param tClass 传入的泛型实参
 * @return T 返回值为T类型
 * 说明:
 *     1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
 *     2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
 *     3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
 *     4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
 */
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
  IllegalAccessException{
        T instance = tClass.newInstance();
        return instance;
}
Object obj = genericMethod(Class.forName("com.test.test"));

5.1.泛型方法的基本用法

public class GenericTest {
   //这个类是个泛型类,在上面已经介绍过
   public class Generic<T>{     
        private T key;

        public Generic(T key) {
            this.key = key;
        }

        //我想说的其实是这个,虽然在方法中使用了泛型,但是这并不是一个泛型方法。
        //这只是类中一个普通的成员方法,只不过他的返回值是在声明泛型类已经声明过的泛型。
        //所以在这个方法中才可以继续使用 T 这个泛型。
        public T getKey(){
            return key;
        }

        /**
         * 这个方法显然是有问题的,在编译器会给我们提示这样的错误信息"cannot reslove symbol E"
         * 因为在类的声明中并未声明泛型E,所以在使用E做形参和返回值类型时,编译器会无法识别。
        public E setKey(E key){
             this.key = keu
        }
        */
    }

    /** 
     * 这才是一个真正的泛型方法。
     * 首先在public与返回值之间的<T>必不可少,这表明这是一个泛型方法,并且声明了一个泛型T
     * 这个T可以出现在这个泛型方法的任意位置.
     * 泛型的数量也可以为任意多个 
     *    如:public <T,K> K showKeyName(Generic<T> container){
     *        ...
     *        }
     */
    public <T> T showKeyName(Generic<T> container){
        System.out.println("container key :" + container.getKey());
        //当然这个例子举的不太合适,只是为了说明泛型方法的特性。
        T test = container.getKey();
        return test;
    }

    //这也不是一个泛型方法,这就是一个普通的方法,只是使用了Generic<Number>这个泛型类做形参而已。
    public void showKeyValue1(Generic<Number> obj){
        Log.d("泛型测试","key value is " + obj.getKey());
    }

    //这也不是一个泛型方法,这也是一个普通的方法,只不过使用了泛型通配符?
    //同时这也印证了泛型通配符章节所描述的,?是一种类型实参,可以看做为Number等所有类的父类
    public void showKeyValue2(Generic<?> obj){
        Log.d("泛型测试","key value is " + obj.getKey());
    }

     /**
     * 这个方法是有问题的,编译器会为我们提示错误信息:"UnKnown class 'E' "
     * 虽然我们声明了<T>,也表明了这是一个可以处理泛型的类型的泛型方法。
     * 但是只声明了泛型类型T,并未声明泛型类型E,因此编译器并不知道该如何处理E这个类型。
    public <T> T showKeyName(Generic<E> container){
        ...
    }  
    */

    /**
     * 这个方法也是有问题的,编译器会为我们提示错误信息:"UnKnown class 'T' "
     * 对于编译器来说T这个类型并未项目中声明过,因此编译也不知道该如何编译这个类。
     * 所以这也不是一个正确的泛型方法声明。
    public void showkey(T genericObj){

    }
    */

    public static void main(String[] args) {


    }
}
6.常见面试题
6.1java中的泛型是如何工作的?什么是类型擦出?

泛型的正常工作是依赖于编译器在编译源码时,先进行类型检查,然后进行类型擦除并在类型参数出现的地方插入强制转化的相关指令。
类型擦除:通过类型参数合并,将泛型类型实例关联到一份字节码上。

6.2什么是泛型中的限定通配符和非限定通配符?

限定通配符:对类型进行了限制。
有两种限制通配符:(1)List <?extends T>通过确保类型必须是T的子类来设定类型的上界。
(2)List<?super T>通过确保类型必须是T的父类来设定类型的下界。

6.3Array中可以用泛型吗?

不可以,Array事实上不支持泛型。

三、JVM

1. 理解JVM
1.1概念

JVM:java虚拟机,可以理解为虚拟的机器,它按照需要加载的字节码文件,通过虚拟引擎解释字节码,将其翻译成CPU可以识别的指令。

1.2为啥要引入JVM?

为了能使java跨平台。原因:在java中,当编译成字节码文件后,操作系统不能直接识别,所以才会引进JVM,由JVM加载字节码文件并在JVM中运行,翻译为CPU可以识别的指令。

1.3JVM的位置

JVM上承开发语言,下接操作系统。

1.4JVM的体系结构

JVM逻辑空间:堆、栈、方法区、本地方法区、程序计数器
在这里插入图片描述

2.堆
2.1概念

存在于JVM中唯一的,大小可改变的,用来存放实体对象的完全二叉树。

2.2堆的三个区域

新生区(伊甸园区)、养老区(老年代)、永久区(元空间)
在这里插入图片描述

2.2.1新生区

类的诞生甚至死亡。它可分为:伊甸园区(所有的对象都是从这个对象new出来的)、辛存区(from区、to区)。

2.2.2养老区

当一个对象经历了15 次GC后还没有死,就会进入养老区。

2.2.3永久区

常驻内存,用来存放JDK自身携带的class对象、interface元数据、java运行的环境类信息。

3.GC
3.1什么是GC ?

GC:垃圾回收机制,释放垃圾所占用的空间,防止内存泄露。有效的使用可以使用的内存,对堆内存中长时间没有使用或死亡的对象进行清理回收。

3.2GC常用的算法
3.2.1引用计数法

给每一个对象加一个计数器,引用时计数器加1,没有引用为0,进行垃圾回收时首先清理计数器为0的对象。
缺点:严重的造成资源浪费,过于繁琐,不能解决循环问题。

3.2.2复制算法

主要发生在新生代,每次GC都会将伊甸园区的活着的对象移到辛存区
优点:没有内存碎片
缺点:浪费内存,总有一半的空间是空的。

在这里插入图片描述
在这里插入图片描述

3.2.3 标记清除算法

首先扫描这些对象,对这些对象进行标记,然后清除未被标记的对象。
优点:不需要额外的空间
缺点:两次扫描严重浪费时间,会产生内存碎片。
在这里插入图片描述

3.2.4标记压缩算法

标记清除算法的升级版,与之不同的是清除完了以后,还要进行扫描,将存活的对象移动到一段。
优点:没有内存碎片
在这里插入图片描述

3.3常见面试题
3.3.1什么是OOM?

OOM:“out of Memory” ,当JVM没有足够的内存为对象分配空间并且垃圾回收器也没有足够的内存空间可以回收时,就会抛出这个error。

3.3.2为什么会OOM?

(1)内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了。
(2)内存溢出:申请使用的内存超过了JVM所能提供的内存大小。

3.3.3什么是GC?为什么会GC ?GC 常用的算法有哪些?

GC:也叫垃圾回收机制,就是释放垃圾所占有的内存空间,防止内存泄露。有效的使用可以使用的内存空间,对堆内存中长时间没有使用的对象或者已经死亡的对象进行清理。
出现GC的原因:GC可以自动监测对象是否超过作用域而达到自动回收内存的目的。
常用的算法:复制算法、标记清除算法、标记压缩算法。

3.3.4什么是Minor GC?什么是Full GC ?他们分别什么时候发时?

(1)Minor GC:也叫轻量级GC,是指发生在新生代的GC 。一般对象都是朝生夕死的,所以Minor GC 非常频繁,一般回收速率也快。
(2)Full GC :也叫重量级GC ,是指发生在老年代的GC,出现Full GC 一般会伴有Minor GC ,但是相比速度比较慢。

3.3.5 触发Minor GC的条件有哪些?

在这里插入图片描述
在进行Minor GC时首先会对老年代连续可用空间和新生代对象所持有的空间进行比较,如果大于则直接进行Minor GC 如果小于,判断HandlerPromationFailure是否开启,如果没有开启则直接进行Full GC ,如果开启继续判断老年代连续可用的最大空间是否大于历次晋升的大小,如果大于则进行Minor GC,反之Full GC.

3.3.6 什么条件下会触发Full GC?

(1)老年代空间不足
(2)持久代空间不足
(3)Minor GC出现promotion failure
(4)统计Minor GC 发生时晋升到老年代的平均大小大于老年代的闲置空间。

3.3.7 Minor GC运行很频繁可能是什么原因造成的?

(1)新生代空间设置太小。
(2)产生太多朝生夕灭的对象导致需要频繁的进行Minor GC。

3.3.8MinorGC运行的很慢有可能是什么原因造成的?

(1)新生代空间设置太大。
(2)对象引用链较长,进行可达性分析时间较长。
(3)新生代survivor设置比较小,清理后剩余对象不能装进去,需要移动到老年代,造成移动开销。
(4)内存分配担保失败,由Minor GC 转为Full GC 。
(5)采用垃圾收集器效率低

3.3.9JVM堆内存溢出后,其他线程是否可以继续工作?

首先堆内存溢出指的是OOM(当JVM没有足够的内存空间为对象分配以及垃圾回收时没有足够个空间进行垃圾回收,就会抛出OOM)。这个要根据情况而定。一般发生OOM的线程一般情况下会死亡,也就是会终结,该线程对象所持有的对象占用的堆都会被GC,释放内存。因为发生OOM之前都要进行GC,就算其他线程能够正常执行,也会因为频繁的GC产生影响。

3.3.10 你知道哪几种垃圾收集器?各自的优缺点?

(1)serial收集器:单线程收集器,收集垃圾时,必须stop the world,使用复制算法。
(2)serial old收集器:serial收集器的老年代版本,单线程收集器,使用标记压缩算法。
(3)GMS收集器:一种以获得最短回收停顿时间为目标的收集器,使用标记清除算法。
运行过程:初始标记、并发标记、重新标记、并发清除。(会产生空间碎片)
(4)G1收集器:利用标记压缩法实现。
运行过程:初始标记、并发标记、最终标记、筛选标记。优点:不会产生空间碎片,可以精确的控制停顿。

3.3.11GSM收集器和G1收集器的区别?

GSM收集器:是一种以获得最短回收停顿时间为目标的收集器,使用标记清除算法。
G1收集器:利用标记整理算法实现。
区别:(1)GSM收集器使用标记清除算法,容易产生空间碎片。G1收集器采用标记压缩算法,不容易产生空间碎片,而却可以精确地控制停顿。
(2)G1收集器可以预测垃圾回收停顿时间。
(3)GSM收集器的收集范围是老年代,可以配合新生代收集器一起使用。G1收集器的收集范围是老年代和新生代。

4.栈
4.1概念

栈:也叫栈内存,主管程序运行,是一种私有的,满足先后进先出的数据结构。生命周期和线程同步。不存在垃圾回收问题。

4.2栈存放的对象

栈存放的对象:对象引用、实例方法、8中基本类型

4.23常见面试题
4.3.1什么情况下会发生栈内存溢出?

栈是私有的主管程序运行的一种后进先出的数据结构,它的生命周期和线程同步,每个方法在执行之前都会创建一个栈帧,存储局部变量表。
(1)当线程请求的栈深度大于虚拟机所允许的最大深度(栈的大小设置太小),将会抛出“stackOverflowError”异常。
(2)程序存在死循环或深度递归也会抛出“stackOverflowError”可以用-Xss调整JVM栈的大小。

5.方法区
5.1概念

和堆一样,方法区是所有线程共享的区域,所有定义的方法信息都保存在该区域。

6.程序计数器
6.1概念

每个线程启动时都会创建一个pc寄存器,保存当前正在执行JVM的指令地址。它的内容总是指向下一条将要执行的指令地址。

6.2常见面试题
6.2.1为什么PC寄存器是私有的?

简单的说就是为了各线程之间独立运算,互不干扰。

7.类加载器
7.1概念

类加载器:java运行环境的一部分,负责动态的讲java类加载到虚拟机的运行空间。
在这里插入图片描述

7.2常见的类加载器种类

(1)启动类加载器 :Bootstarp-JRE/lib/rt.jar
(2)扩展类加载器:Extension-JRE/lib/rt.jar
(3)应用程序加载器:Applicztion

7.3常见面试题
7.3.1什么是双亲委派机制?

双亲委派机制:当一个类加载器收到加载请求时,它首先不会自己加载这个类,而是将这个请求传递给它的父类加载器,每一层如此,所以最终会传到根加载器,如果父类没有办法完成加载请求时才会传给它的子类加载器,子类加载器才会尝试去加载。

7.3.2什么是沙箱安全机制?

沙箱:是指限制java运行的环境,主要限制对系统资源的访问。
沙箱机制:将java代码严格限定在JVM的特定范围内运行,并严格控制对本地资源的访问。
java中的安全模型史:
在java中将要执行的代码分为本地代码和远程代码,本地代码可信,可以访问所有的系统资源。远程代码不可信,在早期的java安全模式中对于未授信的远程代码的安全机制,依赖于沙箱安全。
JDK1.0 :严格的安全机制,严重的限制了程序的扩展,比如用户的远程代码需要访问本地资源就不行。
在这里插入图片描述

JDK1.1:增加了安全模式,用户指定的代码可以对本地资源进行访问。
在这里插入图片描述

JDK1.2再次改进,增加了代码签名。不管是本地代码还是远程代码,都会按照用户设定的安全策略设定的,由类加载器加载到JVM中权限不同的运行空间,来实现差异化的代码执行权限控制。
在这里插入图片描述

最新的安全模式引入域的概念,虚拟机把所有的代码加载到不同的系统域和应用域,系统域负责与关键资源进行交互,应用域不负通过系统域部分代理对各种需要的资源访问。
在这里插入图片描述

四、JMM

1.概念

JMM:java内存模型,在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象描述。

2.作用

(1)缓存一致性协议,用于数据读写规则。
(2)定义线程工作内存和主内存之间的关系。(每个线程都有一个私有的本地内存,本地内存存储了该线程以读写共享边临的副本)
(3)解决共享对象的可见性(volatile关键字)

3.JMM的三大特性
3.1原子性

一个操作不可分割,不可中断。(一个线程在执行的时候不被其他线程干扰)

举例:
面试官拿笔写了段代码,下面这几句代码能保证原子性吗?

int i = 2;
int j = i;
i++;
i = i + 1;
第一句是基本类型赋值操作,必定是原子性操作。

第二句先读取i的值,再赋值到j,两步操作,不能保证原子性。

第三和第四句其实是等效的,先读取i的值,再+1,最后赋值到i,三步操作了,不能保证原子性。

JMM只能保证基本的原子性,如果要保证一个代码块的原子性,提供了monitorenter 和 moniterexit 两个字节码指令,也就是 synchronized 关键字。因此在 synchronized 块之间的操作都是原子性的。
3.2可见性

一个线程修改了共享变量的值,其他线程能够立即得知这个修改。(通过主内存刷新变量的值来实现的)

3.2.1三种可见性的实现方式
3.2.1.1volatile

强制将变量和其他变量状态刷出缓存。

3.2.1.2synchronized

一个变量执行unlock前,必须把变量值同步回主存。

3.2.1.3final

final修饰后的字段在构造器一旦初始化,并且没有发生this逃逸,那么其他线程就可以final字段的值。

3.3有序性

在Java中,可以使用synchronized或者volatile保证多线程之间操作的有序性。

4.JMM的八种内存交互操作

锁定、读取、写入、加载、使用、赋值、存储、解锁
(1)lock(锁定),作用于主内存中的变量,把变量标识为线程独占的状态。
(2)read(读取),作用于主内存的变量,把变量的值从主内存传输到线程的工作内存中,以便下一步的load操作使用。
(3)load(加载),作用于工作内存的变量,把read操作主存的变量放入到工作内存的变量副本中。
(4)use(使用),作用于工作内存的变量,把工作内存中的变量传输到执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作。
(5)assign(赋值),作用于工作内存的变量,它把一个从执行引擎中接受到的值赋值给工作内存的变量副本中,每当虚拟机遇到一个给变量赋值的字节码指令时将会执行这个操作。
(6)store(存储),作用于工作内存的变量,它把一个从工作内存中一个变量的值传送到主内存中,以便后续的write使用。
(7)write(写入):作用于主内存中的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。
(8)unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
我再补充一下JMM对8种内存交互操作制定的规则吧:

不允许read、load、store、write操作之一单独出现,也就是read操作后必须load,store操作后必须write。
不允许线程丢弃他最近的assign操作,即工作内存中的变量数据改变了之后,必须告知主存。
不允许线程将没有assign的数据从工作内存同步到主内存。
一个新的变量必须在主内存中诞生,不允许工作内存直接使用一个未被初始化的变量。就是对变量实施use、store操作之前,必须经过load和assign操作。
一个变量同一时间只能有一个线程对其进行lock操作。多次lock之后,必须执行相同次数unlock才可以解锁。
如果对一个变量进行lock操作,会清空所有工作内存中此变量的值。在执行引擎使用这个变量前,必须重新load或assign操作初始化变量的值。
如果一个变量没有被lock,就不能对其进行unlock操作。也不能unlock一个被其他线程锁住的变量。
一个线程对一个变量进行unlock操作之前,必须先把此变量同步回主内存。

五、并发

1.线程
1.1概念

线程:操作系统的最小操作单位,进程的一个实体,是CPU调度和分配的基本单位。

1.2线程的生命周期
(1)新建

新建(new):用操作符new创建一个线程。

(2)可运行

可运行(Runnable):一旦调用了start方法,就处于可运行状态。

(3)阻塞

阻塞(Blocked):线程视图获取一个内部的对象锁,而这个锁目前被其他线程占有,该线程就处于被阻塞状态。

(4)等待

等待(Waiting):当线程等待另一个线程通知调度器出现一个条件时,这个线程就处于等待状态。

(5)计时等待

计时等待(Time Waiting):调用Thread.sleep、Thread.join、Object.wait、Lock.tryLock、Condition.await方法就会进入计时等待状态。

(6)终止

终止(Terminated):run方法正常退出。

1.3创建一个线程
(1)继承Thread类

步骤:
(1)继承Thread类,重写run方法。
(2)创建Thread对象,调用start方法。

(2)实现Runnable接口

步骤:
(1)实现Runnable接口,重写run方法。
(2)用MyRunnable的对象作为参数实例化Thread,并调用Thread的start方法。

(3)实现Callable接口

步骤:
(1)实现Callable接口,并重写call方法。
(2)创建Callable的实现类实例,创建一个线程池,调用submit方法。如果需要返回值,就调用Future的get方法。

1.4线程常用的几种方法
(1)start()

调用该方法将启动线程

(2)run()

定义线程对象被调度后所执行的操作。

(3)sleep()

调用该方法使线程进入睡眠状态。

1.5常见面试题
1.5.1线程和进程的区别?

(1)线程是进程的的一个实体,是比进程更小的单位。进程是程序的一次执行过程,是程序运行的基本单位是动态的。
(2)进程是相互独立的,但是线程不一定相互独立。

1.5.2线程的sleep()和wait()方法的区别?

(1)sleep()是Thread类的静态方法,wait()是Object超类的成员方法。
(2)sleep()方法需要抛出异常,wait()则不需要。
(3)sleep()可以在任意地方使用,wait()只能在同步方法和同步代码块使用。
(4)在调用sleep()方法过程中,线程不会释放对象锁,而调用wait()方法线程会放弃锁。

1.5.3并发和并行的区别?

并发,从宏观方面来说,并发就是同时进行多种事件,实际上,这几种事件,并不是同时进行的,而是交替进行的,而由于CPU的运算速度非常的快,会造成我们的一种错觉,就是在同一时间内进行了多种事情。
并行,则是真正意义上的同时进行多种事情。这种只可以在多核CPU的基础下完成。

1.5.4线程同步和异步?

线程同步: A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求不到,怎么办,A线程只能等待下去
线程异步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程仍然请求的到,A线程无需等待
同步最最安全,最保险的。而异步不安全,容易导致死锁

1.5.5实现线程同步的方法有哪些?

(1)用synchronized修饰同步方法。
(2)用synchronized{}修饰具体的代码块。

1.5.6同步方法和同步代码块的区别?

(1)同步方法默认用this或当前class对象作为锁,同步代码块可以选择以什么来加锁,比同步方法更细颗度粒。
(2)同步方法用synchronized修饰,同步代码块用synchronized{}修饰。

2.多线程
2.1概念

创建多条线程同时执行任务。

2.2常见面试题
2.2.1多线程与多任务的区别?

多任务是对于操作系统而言的表示一个操作系统可以同时运行多个程序。多线程是针对进程而言的,表示一个进程内部可以同时执行多个线程。

2.2.2多线程与高并发有联系?

多线程在高并发问题中的作用:充分利用计算机资源,使计算机资源在每一刻都能达到最大利用资源,不至于浪费计算机资源。

3.线程池
3.1概念

是多线程处理形式。

3.2 基本组成部分

线程池管理器、工作线程、任务接口、任务队列。

3.3线程池的种类
(1)singleThreadPool

只有一条线程来执行任务。

(2)FixedThreadPool

定长的线程池,有核心线程,没有非核心线程。

(3)CachedThreadPool

可缓存的线程池,没有核心线程,适用于耗时小,任务量大的情况。

(4)ScheduleThreadPool

大小无限制的线程池,支持定时和周期性的执行线程。

3.4线程池的优势
(1)降低资源消耗

重复利用已经创建的线程,近地对资源的消耗

(2)提高响应速率

任务到达时,任务可以不用等到线程创建而执行。

(3)提高线程的可管理性

使用线程池统一分配、调优、监控,从而提高线程的可管理性。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小倪长头发啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值