start
启动一个线程、在新的线程里执行run方法中的代码。 start 方法只是让线程进入就绪状态,cpu的时间片可能还没分给他,每个线程的start() 只能调用一次,调用多次会报IllegalThreadState异常
run
在构造Thread的时候传递了Runable 参数,线程启动会调用Runable中的run方法。否则不会执行任何操作,但可以创建Thread 的子类,覆盖默认行为。
sleep 方法
- 调用sleep 方法 会让当前线程从
RUNNING进入TIMED_WAITING状态(不可能获得时间片,不占用cpu资源) - 其他线程可以调用
interrupt方法 打断正在睡眠的线程,这时sleep会抛出InterruptedException - 睡眠结束后的线程未必立刻得到执行(睡醒了不一定能立刻获得cpu的使用权)
- 建议使用
TimeUnit的sleep方法,可以获得更好的可读性。
小应用 : 防止 CPU 占用 100%
轮询处理 (复习才理解这种轮询~)
单核下 一直 while (true) 占用 cpu 100%
while(true) {
try {Thread.sleep(100);}
catch(Exception e) {}
}
yield 方法
- 会让线程从
Runing进入RUNABLE状态(有机会获得时间片),然后调度其他线程。 - 具体的实现依赖于操作系统的任务调度器。
- 他几乎没有等待时间。
线程优先级
方法 : setPriority(int)
public final static int MIN_PRIORITY = 1; // 最小
public final static int NORM_PRIORITY = 5; // 普通优先级
public final static int MAX_PRIORITY = 10; // 最大优先级
需要注意的是,他仅仅只是一个考量,调度器可以忽略它。
cpu忙的时候,优先级较高的会获得更多时间片。cpu闲的时候,优先级几乎就被忽略了。
join 方法
public class JoinTest {
static int r ;
public static void main(String[] args) {
test1();
System.out.println(r);
}
private static void test1(){
new Thread(()->{
try {
TimeUnit.MILLISECONDS.sleep(1);
r = 10;
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
分析 :
- 主线程和t1并行执行,t1要1ms后才能算出r=10; 解决方法:
- sleep() 不太好 : 不好把控计算时间,实际开发中 并不会明确知道 计算时间。
public static void main(String[] args) throws InterruptedException {
test1();
TimeUnit.MILLISECONDS.sleep(1);
System.out.println(r);
}
- join() 解决 :
join等待线程run方法计算任务结束。 即线程死亡。
在使用
join之前,保证前面的代码是异步的。调用join之后, 阻塞主线程了,这时候是同步的等待t1 线程。 join(long) 参数 时间到了终止等待。
interrupt 线程的正确终止
打断阻塞状态的线程
即断 sleep、wait、join 的线程。 在打断后,
打断标记会被清空。
打断运行状态的线程
打断标志位 终止线程运行。
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true){
Thread thread = Thread.currentThread();
boolean interrupted = thread.isInterrupted();
if (interrupted) {break;}
}
});
Thread.sleep(1000);
t1.interrupt();
}