1 线程状态
2 线程方法
方法 | 说明 |
---|---|
setPriority(int new Priority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程(不推荐使用) |
boolean isAlive() | 测试线程是否处于活跃状态 |
3 停止线程
-
不推荐使用JDK提供的
stop()
、destroy()
方法(已废弃) -
建议线程正常停止(利用次数,不建议死循环)
-
建议使用一个标志位,当
flag = false
时,终止线程运行public class TestStop implements Runnable { // 根据此标志位终止变量 private boolean flag = true; @Override public void run() { while (flag) { System.out.println("run... Thread"); } } // 对外提供方法改变标志位 public void stop() { this.stop = false; } }
4 线程休眠
-
sleep()
制定当前线程阻塞的毫秒数(1秒=1000毫秒) -
sleep()
存在异常InterruptedException
-
sleep()
时间到达后线程进入就绪状态 -
sleep()
可以模拟网络延时,倒计时等// 模拟倒计时 public void tenDown() throws InterruptedException { int num = 10; while (true) { Thread.sleep(1000); System.out.println(num--); if (num <= 0) { break; } } }
-
每个对象都有一个锁,
sleep()
不会释放锁
5 线程礼让
-
礼让线程就是让当前正在执行的线程暂停,但不阻塞
-
礼让将线程从运行状态转为就绪状态
-
此时CPU重新调度,但礼让不一定成功,需要视CPU情况
public class TestYield { public static void main(String[] args) { MyYield myYield = new MyYield(); new Thread(myYield, "Thread_A").start(); new Thread(myYield, "Thread_B").start(); } } class MyYield implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "线程开始执行"); Thread.yield(); // 礼让 System.out.println(Thread.currentThread().getName() + "线程停止执行"); } }
6 线程强制执行
-
join()
合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞(可以理解为插队) -
join()
存在异常InterruptedException
public class TestJoin implements Runnable{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("本线程来了" + i); } } public static void main(String[] args) throws InterruptedException { TestJoin testJoin = new TestJoin(); Thread thread = new Thread(testJoin); thread.start(); // 主线程 for (int i = 0; i < 500; i++) { if (i == 200) { thread.join(); // 插队 } System.out.println("main线程" + i); } } }
7 观测线程状态
JDK中有Thread.State
枚举类型对线程状态进行描述:
-
NEW
:尚未启动的线程处于此状态 -
RUNNABLE
:在Java虚拟机中执行的线程处于此状态 -
BLOCKED
:被阻塞等待监视器锁定的线程处于此状态 -
WAITING
:正在等待另一个线程执行特定动作的线程处于此状态 -
TIMED_WAITING
:正在等待另一个线程执行动作到达指定等待时间的线程处于此状态 -
TERMINATED
:已退出的线程处于此状态
public class TestState {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("*********");
});
// 观察状态
Thread.State state = thread.getState();
System.out.println(state); // NEW
// 观察启动后
thread.start();
state = thread.getState();
System.out.println(state); // RUNNABLE
while (state != Thread.State.TERMINATED) { // 只要线程不终止,就会一直输出状态
Thread.sleep(500);
state = thread.getState(); // 更新线程状态
System.out.println(state); // 输出状态
}
}
}
输出结果:
NEW
RUNNABLE
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
*********
TERMINATED
8 线程的优先级
- Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行
- 线程的优先级用数字表示,范围从1~10,数值越大优先级越高
Thread.MIN_PRIORITY = 1;
Thread.MAX_PRIORITY = 10;
Thread.NORM_PRIORITY = 5;
- 使用
getPriority()
和setPriority(int newPriority)
获取和改变优先级 - 并不是优先级高的线程一定先执行,还是需要服从CPU的调度,优先级高只是被调度的概率更高
public class TestPriority {
public static void main(String[] args) {
// main线程默认优先级5
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
Thread t3 = new Thread(myPriority);
Thread t4 = new Thread(myPriority);
Thread t5 = new Thread(myPriority);
Thread t6 = new Thread(myPriority);
// 先设置优先级,再启动
t1.start(); // 默认优先级5
t2.setPriority(Thread.MIN_PRIORITY); // Thread.MIN_PRIORITY = 1
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY); // Thread.MAX_PRIORITY = 10
t4.start();
// 设置范围只能在1~10这10个整数中
t5.setPriority(-1); // 报错
t5.start();
t6.setPriority(11); // 报错
t6.start();
}
}
class MyPriority implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
}
}
9 守护线程
- 线程分为用户线程和守护(daemon)线程
- 虚拟机必须确保用户线程执行完毕,但不用等待守护线程执行完毕
- 后台记录操作日志、内存监控、垃圾回收等都属于守护线程
- 通过线程的
setDaemon()
方法设置守护线程,参数是一个布尔值,默认为false,设置为true时表示该线程是一个守护线程
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true); // 设置为守护线程
thread.start(); // 此时JVM不会等待守护线程执行完毕
new Thread(you).start();
}
}
class You implements Runnable {
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你一生都开心的活着");
}
System.out.println("========Goodbye World!=========");
}
}
class God implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("上帝保佑着你!");
}
}
}