1:同步与异步 16:park()与unpark()
2:start()和run() 17:park(),unpark()&wait(),notify()
3:sleep() 与 yield() 18:死锁
4:线程优先级 19:Lock接口
5:join()
6:join(毫秒数)
7:interrupt() 方法
8:提前结束线程
9:守护线程
10:临界区与竞态条件(如何解决)
11:synchronized
12:线程8锁
13:线程安全性分析
14:wait()和notify(),notifyAll()
15:sleep()与wait()方法对比
- 需要等待结果返回,才能继续运行就是同步
- 不需要等待结果返回,就能继续运行就是异步
区别:
- 调用start()开启一个新的线程,调用run()方法就是普通方法的调用,不会创建新线程。
- 调用start()方法,会执行run()方法中的代码。
- start()方法不能多次调用,多次调用会出现IllegalThreadsStateException异常。
sleep():让线程进入睡眠
-
调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)。
-
其它线程可以使用 interrupt() 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException。
-
睡眠结束后的线程未必会立刻得到执行,会先进入就绪状态等待cpu分配时间片。
-
建议用 TimeUnit(jdk1.5之后) 的 sleep 代替 Thread 的 sleep 来获得更好的可读性。
//都是睡眠1秒 TimeUnit.SECONDS.sleep(1); Thread.sleep(1000);
yield():让运行状态线程进入就绪
- 调用 Thread.yield() 会让当前线程放弃当前时间片,从 Running(运行状态) 进入 Runnable 就绪状态,然后调度执行其它线程
- 具体的实现依赖于操作系统的任务调度器
二者区别:
- sleep():会释放当前线程占有的时间片,直到睡眠时间结束或被interrupt() 打断后,cpu才会重新为其分配时间片等待cpu重新调用。
- yield():同样会让出时间片,等待cpu重新为其分配时间片,cpu重新调度,只不过没有睡眠时间。
线程优先级后会提示任务调度器去优先调度该线程,但仅仅只是提示,最终的任务调度情况还得由调度器决定,比如cpu比较繁忙时,优先级高的线程会获得更多的时间片。而cpu空闲时,优先级甚至会被忽略进而导致不起作用。
设置优先级:
t1.setPriority(n);
//n[ 1 , 10 ]
//1:最小优先级
//5:默认优先级
//10:最大优先级
join():让当前线程等待另一个线程执行结束后再继续执行当前线程
案例:
static int r = 0;
public static void main(String[] args) throws InterruptedException {
test1();
}
private static void test1() throws InterruptedException {
log.debug("开始");
Thread t1 = new Thread(() -> {
log.debug("开始");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("结束");
r = 10;
});
t1.start();
t1.join();
log.debug("结果为:{}", r);
log.debug("结束");
}
当前案例执行结果为 **r=0** 而不是 **r=10**
分析:
因为主线程和线程 t1 是并行执行的,t1 线程需要 1 秒之后才能算出 r=10
而主线程一开始就要打印 r 的结果,所以只能打印出 r=0。
解决方案:
想要让最终结果为r=10,就需要让主线程等待t1线程执行完毕后,主线程再去打印最终结果(异步变为同步)。即调用join() 方法。
解释: 当前线程等待另一个线程执行,与join() 这个无参数的方法不同,join()方法会让当前线程等待另一个线程结束。而join(500) 表示当前线程最多等待另一个线程500毫秒,如果在5秒没另一个线程没有执行完毕,将不再等待,继续执行当前线程。
static int r1 = 0;
public static void main(String[] args) throws InterruptedException {
test3();
}
public static void test3() throws InterruptedException {
Thread t1 = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
r1 = 10;
});
long start = System.currentTimeMillis();
t1.start();
// 线程执行结束会导致 join 结束
t1.join(