线程状态

线程

exe双击启动一个程序
线程是一个程序里不同的执行路径。
调用run方法,还是一条路径,要启动多线程,需要调用start方法。

cpu没有线程的概念,只知道取指令运行。而多线程就是说,如果是单核cpu,它就按照时间片交替执行这些线程。

启动线程方式

  1. extends Thread 重写run方法,直接调用start启动
    new Thread().start();
  2. implement Runnable 重写run方法,在thread对象中,传入Runnable对象,调用start启动
    new Thread(new MyRun).start();
  3. Executors.newCachedThread 线程池启动
  4. 用lambda表达式
    new Thread(() -> {sout("hello");}).start();
    1
    2
    3
    4
    5
    6
    7
    8
    9
    T t = new T();
    new Thread(t::fun(), "name").start();
    // 1.8之前是下面的写法
    new Thread(new Runnable() {
    @override
    public void run() {
    t.fun();
    }
    }).start();

yield、sleep、join

  1. yield本质上是让出一下cpu,返回就绪状态。之后还是会参加cpu争抢。
  2. sleep就是该线程睡一会,返回阻塞态,规定时间后自动复活。
  3. join其实是等待其他线程结束再继续运行。比如在t1线程中调t2.join,就是t1先暂停,t2执行完了,再回到t1继续执行。
    【比如在顺序执行几个线程的时候,可以使用join】

线程状态

在这里插入图片描述

  • JVM是跑在操作系统上的一个普通程序。
  • 正常结束线程,就相当于线程关闭了。
  • 起一个线程,正常来说,就是os中有一个线程和它一一对应。但是虚拟机启动完了之后,本身这个虚拟机里头还会起GC线程之类的,所以操作系统起的线程要大于你原来的线程。
  • stop()不建议使用了
  • interrupt()在底层控制流程中有使用。自己写工程代码很少有人用它来控制业务逻辑。平时使用场景:sleep了两天,调用interrupt()来catch异常。sleep、join、wait的时候,都有可能被打断(interrupt)打断后会抛出异常,你需要进行catch。如果catch到一个异常,接下来的操作需要你根据情况来完成。

加锁的方法和不加锁的方法可以同时运行。
模拟银行账户。对业务写加锁,读不加锁,可能会出现什么问题?脏读。比如setName的方法中,sleep几秒,getName会读到还没有commit的数据。但是能不加就不加,效率太低。