Java中的多线程

Posted by KANG's BLOG on Tuesday, March 15, 2022

1. 线程状态

  1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
  2. RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的成为“运行”。 线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得cpu 时间片后变为运行中状态(running)。
  3. 阻塞(BLOCKED):表线程阻塞于锁。
  4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
  5. 超时等待(TIME_WAITING):该状态不同于WAITING,它可以在指定的时间内自行返回。
  6. 终止(TERMINATED):表示该线程已经执行完毕。

2. Thread类提供的方法

run()和start()

start()会创建新的线程,然后获得资源后执行内部run()方法 而run是当前线程内直接调用,并不创建新的线程

sleep()

使当前线程进入停滞状态(阻塞状态),让出cpu使用权,留一定时间让其他线程有机会执行。由于sleep()是静态方法所以不会破坏对象所持有的机锁,所以在同步块中调用sleep(),不会释放对象锁,其他线程无法访问此对象。

join()

当前线程需要等待previousThread线程终止之后才从thread.join返回。简单来说,就是线程没有执行完之前,会一直阻塞在join方法处。

3. 线程类型

Java中线程分为用户线程(User thread)和守护线程(Daemon thread)

守护线程,顾名思义,是所有用户线程的“守护者”,即当jvm中还存在至少一个用户线程没有结束,则守护线程就全部工作。

守护线程最典型的应用场景就是GC。

用户线程和守护线程使用上几乎没有区别,唯一区别就是当用户线程全部退出运行时,虚拟机也就结束了,无论是否有工作中的守护线程。

Java中设置一个线程为守护线程的方法是在线程启动前,调用setDaemon()方法:

Thread t = new Thread(() -> {
  System.out.println("i'm a daemon thread");
});
t.setDaemon(true);
t.start();