1. 线程终止 —— 通知方式
通过在 T1 线程中修改 T2 线程中的控制变量,来实现 T1 线程通知 T2 线程终止。
示例如下:
/**
* @description: 线程的终止和退出测试
* @author: Liuwanqing
* @date: 2022-10-14 17:00
*/
public class ThreadExit_ {
public static void main(String[] args) throws InterruptedException {
Th t = new Th();
t.start();
// main 通过控制 loop ,让 t 终止 —— 通知方式
Thread.sleep(5 * 1000); // main 线程先休眠 5 秒,再使得 t 线程终止
t.setLoop(false);
}
}
class Th extends Thread {
private int count = 0;
private boolean loop = true; // 控制线程终止
public void setLoop(boolean loop) { // 创建修改 loop 值的接口,以便其他线程控制 Th 线程终止
this.loop = loop;
}
@Override
public void run() {
while (loop){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("T 在运行了~~~");
}
}
}
2. 线程常用方法
(1) setName
—— 设置线程名称
(2)getName
—— 返回线程名称
(3) start
—— 使线程开始执行
(4) run
—— 调用线程对象的 run 方法
(5) setPriority
—— 更改线程的优先级 (线程优先级范围 1 5 10)
不一定线程优先级高的就一定先执行,与 CPU 调度有关 (但是大部分都是优先级高的先执行)
(6) getPriority
—— 获取线程的优先级
System.out.println(t.getName() + " 的优先级是" + t.getPriority());
(7) sleep
—— 线程休眠
(8) interrupt
—— 中断线程
当某个线程在休眠时,得到interrupt通知,会终止休眠 (中断线程不等于终止线程)
测试代码:
package threadUse;
/**
* @description: 测试线程的方法
* @author: Liuwanqing
* @date: 2022-10-14 17:20
*/
public class ThreadMethod {
public static void main(String[] args) throws InterruptedException {
testThread t = new testThread();
t.setName("LiuWanqing");
t.setPriority(Thread.MIN_PRIORITY);
t.start();
// 主线程打印 5次 ”不够,还饿“,终止子线程的休眠
for (int i=0; i<5; i++){
Thread.sleep(1000);
System.out.println("不够,还饿");
}
System.out.println(t.getName() + " 的优先级是" + t.getPriority());
t.interrupt(); // 执行到这里,中断 t 的休眠
}
}
class testThread extends Thread {
@Override
public void run() {
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() + " 在吃包子~~ " + i);
try {
System.out.println(Thread.currentThread().getName() + " 在休眠中~~");
Thread.sleep(10 * 1000); // 休眠 3 秒
} catch (InterruptedException e) {
// 线程执行到 interrupt 方法 ,会抛出一个异常,这里可加入自己的业务代码
System.out.println(Thread.currentThread().getName() + " 被 interrupt 了");
}
}
}
}
(9)yield
—— 线程礼让
T1 线程让出 CPU,让 T2 线程执行,这种礼让不一定成功 ( CPU 判断资源利用程度,决定是否礼让)
注: 自己礼让对方,因此要自身调用 yield
(10)join
—— 线程的插队
线程一旦插队成功,肯定先执行完插入线程的所有任务。如 T1 正在执行,在执行中调用 T2.join() ,这时 CPU 先执行 T2,直到 T2 执行完,再去执行 T1。
注: 其他线程插队,因此是插队的线程调用 jion
主线程让子线程插队示例代码:
package threadUse;
/**
* @description: 线程的插队和礼让方法测试
* @author: Liuwanqing
* @date: 2022-10-14 17:48
*/
public class ThreadMethod01 {
public static void main(String[] args) throws InterruptedException {
T3 thread = new T3();
thread.start();
// 实现主线程吃了 5 个包子后,让子线程全部吃完
for (int i=0; i<20; i++){
Thread.sleep(1000);
System.out.println(" 主线程吃了" + i + "个包子");
if(i == 5){
System.out.println("主线程吃了 5 个包子后,让子线程全部吃完");
thread.join();
}
}
}
}
class T3 extends Thread {
@Override
public void run() {
for (int i=0; i<=20; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(" 子线程吃了" + i + "个包子");
}
}
}
(11)getState
得到线程状态
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) {
throw new RuntimeException(e);
}
}
});
// 观察状态
Thread.State state = thread.getState();
System.out.println(state);
// 观察启动后
thread.start();
state = thread.getState();
System.out.println(state);
// 不终止一直打印状态
while (state != Thread.State.TERMINATED){
Thread.sleep(100);
state = thread.getState();
System.out.println(state);
}
}
3. 用户线程和守护线程
用户线程:也叫工作线程,当线程任务执行完或者以通知的方式结束
守护线程:为工作线程服务,当用户线程结束,守护线程自动结束,如垃圾回收机制就是常见的守护线程
public class testDaemon {
public static void main(String[] args) {
You you = new You();
God god = new God();
Thread thread = new Thread(god);
thread.setDaemon(true);
thread.start();
new Thread(you).start();
}
}
class You implements Runnable {
@Override
public void run() {
for (int i=0; i<36500; i++){
System.out.println("你开心的活着");
}
}
}
class God implements Runnable {
@Override
public void run() {
while (true) {
System.out.println("上帝保佑你");
}
}
}