Java并发编程学习笔记--基础篇一

文章目录

    • 线程基础知识
      • 1.1 什么是线程
      • 1.2线程的创建方式
      • 1.3线程的创建方式对比
      • 1.4线程上下文切换
      • 1.5线程死锁
          • 1.5.1什么是线程死锁
          • 1.5.2死锁产生必须具备的四个条件
          • 1.5.3如何避免线程死锁
      • 1.6守护线程和用户线程
      • 1.7简单了结ThreadLocal

线程基础知识

1.1 什么是线程

    操作系统分配资源时是把资源分配给进程的,一个进程中至少有一个线程,多个线程共享操作系统分配给进程的资源,但是这些资源中cpu资源比较特殊,他是被分配给单个线程的。因为真正要占用cpu运行的是线程。

1.2线程的创建方式

java中有四种创建线程的方式:
第一种:继承Thread类重写run方法。
第二种:实现Runnable接口的run方法。
第三种:实现Callable接口的call方法。
第四种:通过线程池去创建。

1.3线程的创建方式对比

继承Thread类:优点是方便传递参数,可以在子类里新加成员变量,通过构造函数和set方法进行传递。缺点是java不支持多继承,继承了Thread类,子类便不可以继承其它类了。
实现Runnable接口:优点是实现了任务与代码的分离,当多个线程执行一样的任务时只需要一份任务代码。缺点是只能使用主线程中被声明为final的变量。
实现Callable接口:最突出的俩个优点,call方法可以抛出异常,可以获取到任务的返回值。缺点是编程稍显复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法,而不像继承Thread类那样直接在run方法中使用this就可以了。
使用线程池去创建:优点提高响应速度,降低系统资源的消耗,提高线程的可管理性。缺点是每次通过new Thread()创建新对象性能不佳。

1.4线程上下文切换

在多线程编程中,线程个数往往多于cpu的个数,而每一个cpu同时只能被一个线程使用。cpu的资源分配采用了时间片轮的策略,当线程使用完cpu分配的时间片就会处于就绪状态并让出cpu给其它线程使用,这就是线程的上下文切换。
线程上下文切换的时机包括:线程使用完时间片处于就绪状态和当前线程被其它线程中断。

1.5线程死锁

1.5.1什么是线程死锁

死锁是指两个或两个以上线程在执行过程中,因争夺资源造成的互相等待现象。

1.5.2死锁产生必须具备的四个条件

互斥条件:线程对获取到的资源进行排他性使用,不允许其它线程请求获取该资源。
请求并持有条件:线程已经持有至少一个资源,并提出了获取已经被其它线程所占有的新资源。
不可剥夺条件:线程获取到的资源在被自己使用完之前不能被其它线程抢占,只能自己使用完后释放。
环路等待条件:一个线程集合(t0,t1,t2,…tn),t0等待t1占用的资源,t1等待t2占用的资源,…tn等待t0占用的资源。

1.5.3如何避免线程死锁

要想避免线程死锁,只需要破坏掉至少一个构成死锁的必要条件即可,目前只有请求并持有和环路等待是可以被破环的。可以通过请求资源的有序性破环资源请求并持有条件和环路等待条件来避免死锁。什么是请求资源的有序性,简单来说就是多个线程都使用相同的资源请求顺序。举个简单例子有线程A和线程B有资源一和资源二,线程A和B都是先获取到资源一再去获取资源二,这就是多线程获取资源的有序性。

1.6守护线程和用户线程

java中的线程分为俩类,分别为daemon线程(守护线程)和user线程(用户线程)。
用户线程和守护线程有什么区别呢?
当最后一个用户线程结束时,jvm会正常退出,而不管当前是否有守护线程,也就是说守护线程是否结束并不会影响jvm退出。
如何将线程设置为守护线程?
只要将线程的daemon参数设置为true即可。

1.7简单了结ThreadLocal

ThreadLocal是JDK包提供的,他提供了线程本地变量也就是说如果你创建一个变量为ThreadLocal变量,访问这个变量的每个线程都会有这个变量的一个本地副本,当多个线程操作这个变量时,实际操作的是自己本地内存里的变量,从而避免了线程安全问题。

你可能感兴趣的:(java并发编程)