方法
void |
**[setPriority](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#setPriority-int-)**(int newPriority) 更改此线程的优先级。 |
---|---|
static void |
**[sleep](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#sleep-long-)**(long millis) 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。 |
void |
**[join](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#join-long-)**(long millis) 等待这个线程死亡最多 millis 毫秒。 |
static void |
**[yield](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#yield--)**() 对调度程序的一个暗示,即当前线程愿意产生当前使用的处理器。 |
void |
**[interrupt](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#interrupt--)**() 中断这个线程。 |
boolean |
**[isAlive](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#isAlive--)**() 测试这个线程是否活着。 |
long |
**[getId](https://www.matools.com/file/manual/jdk_api_1.8_google/java/lang/Thread.html#getId--)**() 返回此线程的标识符。 |
停止线程
- 不推荐使用:stop、destroy方法
- 推荐线程自己停止
- 使用标志位进行中止变量,当flag=false,则线程中止运行 ; 或使用有限次的循环代替死循环
public class ThreadBase04 implements Runnable {
// 设置标识位
private boolean flag = true;
// 设置一个公开的方法停止线程,转换标识位
public void stop() {
this.flag = false;
}
@Override
public void run() {
int i = 0;
// 线程体内使用该标识进行控制
while (flag) {
System.out.println("hello! " + i++);
}
}
public static void main(String[] args) {
ThreadBase04 threadBase04 = new ThreadBase04();
new Thread(threadBase04).start();
for (int i = 0; i < 500; i++) {
System.out.println(Thread.currentThread().getName() + "运行 : " + i);
}
threadBase04.stop();
}
}
线程休眠
- 存在异常 InterruptedException
- sleep到达时间后进入就绪状态,等待CPU资源再执行。
- 可以用于模拟网络时延、倒计时
- 每个对象都有一个锁,sleep不会释放锁
后面都用JUC的TimeUnit进行休眠
Thread.sleep(1000); // 休眠一秒钟
线程礼让 yield
- 让当前正在执行的线程暂停,但是不阻塞
- 将线程从运行状态转为就绪状态(释放CPU资源)
- 让cpu重新调度,礼让不一定成功,看CPU。
```java
public class TestYield {
public static void main(String[] args) {
} }MyYield myYield = new MyYield();
new Thread(myYield, "a").start();
new Thread(myYield, "b").start();
class MyYield implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + “ 线程开始执行”); // 礼让 Thread.yield(); System.out.println(Thread.currentThread().getName() + “ 线程结束执行”); } }
礼让不一定成功:
a 线程开始执行 a 线程结束执行 b 线程开始执行 b 线程结束执行
a 线程开始执行 b 线程开始执行 a 线程结束执行 b 线程结束执行
<a name="TEnqG"></a>
# join
- 合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞。 哪个线程调用了join方法,当前线程就等待哪个线程执行完毕。
- 类似于插队
```java
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " 线程执行 " + i);
}
}
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin = new TestJoin();
Thread vip = new Thread(testJoin, "vip");
vip.start();
for (int i = 0; i < 200; i++) {
System.out.println(Thread.currentThread().getName() + " 线程执行 " + i);
if (i == 70) {
// 主线程被阻塞,等待vip线程执行完之后才会执行主线程
vip.join();
}
}
}
}
观测线程状态
- NEW
尚未启动的线程处于此状态。 - RUNNABLE
在Java虚拟机中执行的线程处于此状态。 - BLOCKED
被阻塞等待监视器锁定的线程处于此状态。 - WAITING
正在等待另一个线程执行特定动作的线程处于此状态。 - TIMED_WAITING
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。 - TERMINATED
已退出的线程处于此状态。Thread thread = new Thread(() -> { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("....."); } }); // 观察 NEW状态 Thread.State state = thread.getState();
线程优先级
- 线程调度器按照优先级决定应该调度哪个线程来执行。效果不明显,优先级高也不一定先执行
- 范围1-10
Thread.MIN_PRIORITY=1
Thread.MAX_PRIORITY=10
Thread.NORM_PRiORITY=5
- getPriority() 或者 setPriority()
守护线程
- 线程分为用户线程和守护线程
- 虚拟机必须确保用户线程执行完毕
- 虚拟机不用等待守护线程执行完毕,例如:后台记录操作日志、监控内存、垃圾回收
Thread thread = new Thread(...);
thread.setDaemon(true); // 默认为false,代表用户线程
thread.start();
判断线程是否活动
thread.isAlive()
判断该线程是否处于活动状态,活动状态就是线程已启动并且尚未终止。
获取线程id
thread.getId()
main线程的id是1,线程结束后,该id可以被重新赋值给其他线程。
但是在运行期间,线程的id是唯一的。
Object.wait
使线程状态从RUNNABLE转换为WAITING
调用wait()方法前线程必须持有对象的锁。 线程调用wait()方法时,会释放当前的锁,直到有其他线程调用notify()/notifyAll()方法唤醒等待锁的线程。
需要注意的是,其他线程调用notify()方法只会唤醒单个等待锁的线程,如有有多个线程都在等待这个锁的话不一定会唤醒到之前调用wait()方法的线程。
同样,调用notifyAll()方法唤醒所有等待锁的线程之后,也不一定会马上把时间片分给刚才放弃锁的那个线程,具体要看系统的调度。
wait和sleep的区别
- 来自不同的类:wait来自于Object类,sleep来自于Thread类
- 锁的释放:wait释放锁,sleep不释放锁
- 使用的范围不同:sleep可以在任意地方使用,wait只能在同步代码块中使用