常见方法表格
方法名 | 功能说明 | 注意 |
start() | 启动一个新线 程,在新的线程 运行 run 方法 中的代码 | start 方法只是让线程进入就绪,里面代码不一定立刻 运行(CPU 的时间片还没分给它)。每个线程对象的 start方法只能调用一次,如果调用了多次会出现 IllegalThreadStateException |
run() | 新线程启动后会 调用的方法 | 如果在构造 Thread 对象时传递了 Runnable 参数,则 线程启动后会调用 Runnable 中的 run 方法,否则默 认不执行任何操作。但可以创建 Thread 的子类对象, 来覆盖默认行为 |
getName() | 获取线程名 | |
setName(String) | 修改线程名 | |
getPriority() | 获取线程优先级 | |
setPriority(int) | 修改线程优先级 | java中规定线程优先级是1~10 的整数,较大的优先级 能提高该线程被 CPU 调度的机率 |
getState() | 获取线程状态 | Java 中线程状态是用 6 个 enum 表示,分别为: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED |
isInterrupted() | 判断是否被打 断, | 不会清除 打断标记 |
isAlive() | 线程是否存活 (还没有运行完 毕) | |
interrupt() | 打断线程 | 如果被打断线程正在 sleep,wait,join 会导致被打断 的线程抛出 InterruptedException,并清除打断标记 ;如果打断的正在运行的线程,则会设置打断标记 ;park 的线程被打断,也会设置打断标记 |
interrupted() | 判断当前线程是 否被打断 | 会清除 打断标记 |
currentThread() | 获取当前正在执 行的线程 | |
sleep(long n) | 让当前执行的线 程休眠n毫秒, 休眠时让出 cpu 的时间片给其它 线程 | |
yield() | 提示线程调度器 让出当前线程对 CPU的使用 |
start()与run()
run还是让主线程操作,start可以让线程就绪。我们可以查看调用start前后线程的状态
Thread t = new Thread("线程状态");log.debug("{}", t.getState());t.start();log.debug("{}", t.getState());
如果两次调用start,会报异常 IllegalThreadStateException。
sleep与yield
可以打印一下状态。sleep会让线程从Running->Timed Waiting
Thread t1 = new Thread(()->{try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}},"线程状态");t1.start();log.debug("t1 state:{}", t1.getState());Thread.sleep(500);log.debug("t1 state:{}", t1.getState());
其他线程可以执行interrupt方法,打断sleep的线程
Thread t1 = new Thread(()->{try {Thread.sleep(2000);} catch (InterruptedException e) {log.debug("I'm interrupted");}},"线程状态");t1.start();log.debug("t1 state:{}", t1.getState());Thread.sleep(500);t1.interrupt();
yield,让线程从Running到Runnable状态。也就是说,调用了yield会让线程进入Runnable状态,但有可能还会继续给这个线程分配时间片,导致没有将cpu资源让出去,但是sleep会真正让出cpu资源,cpu调度时不会考虑sleep的线程。
setPriority优先级
线程优先级会提示调度器优先调度该进程,但是调度器可以忽略它,cpu忙的时候,优先级高的获得的时间片多,但是cpu闲的时候,优先级几乎没用。
看看源码,分为最小、默认、最大优先级。
sleep应用
在没有利用cpu计算时,不要让while空转浪费cpu,这时候就需要sleep让出cpu使用权。
while(true){Thread.sleep(50);}
sleep适用于无需锁同步的场景。
join应用——线程同步与限时同步
join可以等待线程结束,确保正确获取结果。
当我们不使用join,可能无法正确获取a的结果。
public class State {static int a = 10;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{a = 20;},"线程状态");t1.start();log.debug("{}", a);}
}
使用之后:
@Slf4j(topic = "c.test")
public class State {static int a = 10;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{a = 20;},"线程状态");t1.start();t1.join();log.debug("{}", a);}
}
interrupt打断
1、可以打断阻塞的线程,sleep、wait、join,打断后会抛出异常,有打断标记。
2、打断正常线程,并不会真的打断,只是添加打断标记,正常线程可以通过检查自己的打断标记来查看是否被打断。
打断park线程
使用LockSupport.park()会让线程进入WAITING状态。
@Slf4j(topic = "c.test")
public class State {static int a = 10;public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {log.debug("park······");LockSupport.park();log.debug("unpark``````");log.debug("打断状态 {}", Thread.currentThread().isInterrupted());
// log.debug("打断状态 {}", Thread.currentThread().interrupted());LockSupport.park();log.debug("再一次unpark");});t.start();Thread.sleep(1000);t.interrupt();}
}
park遇到isInterrupted()是true失效,可以用interrupted方法,可以看到这时线程就被park了。
@Slf4j(topic = "c.park")public class Park {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {log.debug("park······");LockSupport.park();log.debug("unpark``````");// log.debug("打断状态 {}", Thread.currentThread().isInterrupted());log.debug("打断状态 {}", Thread.currentThread().interrupted());LockSupport.park();log.debug("再一次unpark");});t.start();Thread.sleep(1000);t.interrupt();}}