线程概述

在一个操作系统中,每个独立执行的程序都可以称为一个进程。线程是进程的执行路径。

多线程的实现方案

  1. 多线程通过继承Thread类,重写run方法,创建继承Thread的类的对象,然后调用start方法进行启动线程;
  2. 多线程通过实现Runnable接口,重写run方法,创建实现Runnable接口的类的对象,然后创建一个Thread对象并接收上面对象作为参数,然后调用start方法进行启动线程。

    多线程的生命周期

    多线程的生命周期分为:新建、就绪、运行、阻塞、死亡五个状态。

    多线程同步

  3. 由于多线程中CPU分配线程的执行权限是随机性的,因此在开启多线程时有可能会重复操作共享数据,需要注意线程的同步。
  4. 需要增加同步代码块或者同步方法锁。
  5. 同步锁使用关键字synchronized需要加上所对象,一般来说同步代码块可以使用任意的对象,但需要锁一致,可使用this,创建一个实现Runnable接口的对象,然后开启对个Thread线程;如果是方法锁,如果要保持锁一致,只能使用字节码对象类名.class或者对象名.getClass()。

    死锁问题

  6. 在一个线程或者两个线程中;
  7. 一个线程中开启一个if语句中有两个嵌套同步代码块使用两个锁对象else语句中也有两个嵌套同步代码块锁对象是if语句中顺序相反的锁对象或者两个线程中第一个线程使用两个嵌套的同步代码块使用两个锁对象和第二个线程使用两个嵌套的同步代码块使用锁对象是第一个线程中顺序相反的两个锁对象;
  8. 由于在嵌套的两个锁对象中,开启一个线程的条件执行语句或者开启两个线程时会出现同时锁住两个锁对象,造成死锁问题。

    多线程通信

  9. 生活中经常会出现这样的场景,同时去操作一件事情,如对数据的存储和取出。称之为多线程之间的通信。假如有两个线程同时去操作同一个存储空间,其中一个线程负责对数据的存储,另一个线程则负责对数据的取出;
  10. 我们要有一个先后的顺序,如果没有数据的存储,就不允许取出,或者在存储的过程中,也是不允许取出的;
  11. 这时候我们需要加入一个同步代码块的所对象;
  12. 由于CPU的线程分配执行权的随机性,这时候会出现存储一大片,取出一大片的情况。
  13. 因此我们需要加入,wait方法和notify方法进行判断,存储:当没有存储时进行存储,有存储时,唤醒同一锁对象的任意一个线程,当前等待;取出:当有存储,就取出,没有存储就唤醒同一锁对象的任意一个线程,当前等待。