线程调用共享变量的wait(),此调用线程会被阻塞挂起,
直到发生以下情况:
调用共享变量的wait() 方法时, 选哟获取骑监视器锁
Demo02
notifyAll()
多个线程时随机唤醒
notifyAll(), 唤起所有
Demo03.java
等待线程执行终止的方法
(等待某几件事情完成后才能继续往下执行,
比如多线程加载资源, 需要等待多个线程全部加载完毕再汇总处理)
Demo04_join.java
public static native void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos) throws InterruptedException;
调用线程会暂时让出指定时间的执行权, 不参与CPU调度,
但是该线程拥有所有的监视器资源, 比如锁持有不让出.
Demo05_Sleep.java
当一个线程处于睡眠状态时, 另一个线程中断它, 则在sleep()调用处抛出异常
Demo05_SleepInterruptedException.java
yiled 屈服;出产,产生;放弃;投降;
让出CPU执行权.
一般会很少用这个方法, 在调试或者测试时使用或许可以帮助复现由于并发竞争条件导致的问题
* sleep与yield区别
| sleep | yield |
| --- | --- |
|阻塞线程(挂起指定时间) | 不被阻塞挂起, 线程让出剩余时间片, 处于就绪状态 |
|期间线程调度器不会取调用线程 | 线程调度器下一次调度可能会调用当前线程执行 |
## 6. 线程中断
设置线程中断标志, 不能直接终止线程, 而是被中断线程根据中断状态自行处理
| method | function | description |
| --- | --- |
|void interrupt() | 中断线程 | 别的线程调用本线程的interrupt(), 仅仅设置标志, 并不会中断线程; 如果调用时本线程被阻塞挂(wait,join,sleep), 则会抛出InterruptedExceptiony异常(标记就会失败) |
|boolean isInterrupted() | 检测当前线程是否被中断 | 是则返回true |
|boolean interrupted() | 检测当前线程是否被中断 | 是则返回true, 并清除中断标志 |
**需要注意的是: interrupted() 是静态方法, 而且内部是操作当前线程, 而非操作 调用interrupted()的实例对象的中断标志**
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
Demo07_DetermineIfTheThreadIsTerminatedByInterruptFlag.java```
Demo07_IsInterruptedAndInterrupted.java
CPU在同一时刻只能被一个线程使用, CPU资源分配采用时间片轮转的策略;
给每个线程分配一个时间片, 使用完这个时间片后就会切换到就绪状态, 让出CPU让其他线程使用;
多个线程在执行过程中, 因相互争夺对方已经持有的资源造成相互等待而无法继续运行下去;
4个条件:
Demo08_DeadLock_Why.java
只要破坏其中至少一个条件; 只有 请求并持有 和 环路可以被破坏
使用资源申请的有序原则就可以避免死锁
Demo08_DeadLock_How.java
代码中, threadA 和 threadB 在start() 之后同时去抢占resourceA,
但是只有一个线程可以获取到resourceA的监视器锁, 如果threadA获取到, 则threadB 只能被组撒等到resourceA被释放后,
这时 threadA 可以继续获取resourceB 的监视器锁, 直到 resourceA 和 resourceB 都被threadA释放后, threadB就
可以从阻塞到激活态, 从而避免了死锁;
比如gc线程是一个守护进程, 如果所有用户线程已经结束, 这时gc的存在也就失去了意义
当当前进程中不存在用户线程, 虽然还存在运行任务的守护进程, JVM也会直接结束
Demo09_DaemonAndUser
附:
可在使用jdk的工具jps命令查看jvm是否还在运行;
Linux 也可用 ps -eaf|grep java查看
public final void setDaemon(boolean on) {...}
多线程范围同一个共享变量, 对一个共享变量进行写入时, 容易出现并发问题;
为了保证线程安全, 一般需要对其进行适当同步;
同步的并发一般就是加锁; 需要对锁有一定了解, 加重了使用者的负担;
需求: 创建一个变量后, 每个线程对其访问时都是自己线程的变量;
ThreadLocal 可以做到;
ThreadLocal 给线程提供了本地变量, 当线程访问时就会创建一个本地副本, 从而避免线程安全问题;
Demo10_Instance.java
Demo10_Principle.java
即: 父线程中设置的值, 在子线程访问不到
**原因: 由get()可见, 调用的是当前线程: **
public T get() {
Thread t = Thread.currentThread();
...
```
解决ThreadLocal不支持继承性的问题
重写了三个方法
Demo10_NoSuppotInheritance.java
需要子线程可以获取辅线程的ThreadLocal变量的情况:
原文:https://www.cnblogs.com/52liming/p/11080397.html