Java 线程详解

本文主要介绍 Java 的 Thread 类一些用法。

博主博客

自定义测试类

	private static class NukixThread extends Thread {
		
		public NukixThread(String name) {
			super(name);
		}

		@Override
		public void run() {
			System.out.println("线程 ID: " + getId() + ", 线程名称: " + getName());
		}
	}

一、isAlive、sleep、interrupt和isInterrupted

isAlive: 判断线程是否存活。
sleep: 使线程休眠指定的时间(毫秒)。
interrupt: 中断线程的休眠状态, 比如令 sleep 抛出 InterruptedException 的异常。
isInterrupted: 判断线程是否被中断。

例子

	NukixThread A = new NukixThread("A") {
			@Override
			public void run() {
				super.run();
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("A 执行结束");
			}
		};
		A.start();
		
		
		NukixThread B = new NukixThread("B") {
			@Override
			public void run() {
				super.run();
				
				for (int i = 0; i < 2; i++) {
					// A.interrupt();
					System.out.println("A.isAlive: " + A.isAlive() + ", A.isInterrupted: " + A.isInterrupted());
					try {
						Thread.sleep(5000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				System.out.println("B 执行结束");
			}
		};
		B.start();

输出

线程 ID: 14, 线程名称: A
线程 ID: 15, 线程名称: B
A.isAlive: true, A.isInterrupted: false
A 执行结束
A.isAlive: false, A.isInterrupted: false
B 执行结束

当上面代码 A.interrupt(); 取消注释结果输出

java.lang.InterruptedException: sleep interrupted
线程 ID: 14, 线程名称: A
线程 ID: 15, 线程名称: B
A.isAlive: true, A.isInterrupted: false
	at java.base/java.lang.Thread.sleep(Native Method)
	at demo2.Main1$1.run(Main1.java:19)
A 执行结束
A.isAlive: false, A.isInterrupted: true
B 执行结束

二、wait、notify和notifyAll

wait: 使当前线程进入等待状态, 并且让出锁, 需要通过 notify 或者 notifyAll 进行唤醒。
notify: 唤醒正在等待的一个线程。
notifyAll: 唤醒正在等待的所有线程。

例子

	private static final Object lock = new Object();
	private static int count = 0;
	
	public static void main(String[] args) throws Exception {
		
		NukixThread A = new NukixThread("A") {
			@Override
			public void run() {
				super.run();
				
				for (int i = 0; i < 3; i++) {
					synchronized (lock) {
						try {
							lock.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					System.out.println(getName() + ": " + count++);
					synchronized (lock) {
						lock.notify();
					}
				}
				
				
				
				System.out.println("A 执行结束");
			}
		};
		
		NukixThread B = new NukixThread("B") {
			@Override
			public void run() {
				super.run();
				
				for (int i = 0; i < 3; i++) {
					synchronized (lock) {
						try {
							lock.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					System.out.println(getName() + ": " + count++);
					synchronized (lock) {
						lock.notify();
					}
				}
				
				System.out.println("B 执行结束");
			}
		};
		
		NukixThread C = new NukixThread("C") {
			@Override
			public void run() {
				super.run();
				
				for (int i = 0; i < 3; i++) {
					System.out.println(getName() + ": " + count++);
					synchronized (lock) {
						lock.notify();
					}
					
					synchronized (lock) {
						try {
							lock.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
				
				System.out.println("C 执行结束");
			}
		};
		
		A.start();
		B.start();
		C.start();
		
	}

输出

线程 ID: 14, 线程名称: A
线程 ID: 15, 线程名称: B
线程 ID: 16, 线程名称: C
C: 0
A: 1
B: 2
C: 3
A: 4
B: 5
C: 6
A: 7
A 执行结束
B: 8
B 执行结束
C 执行结束

从输出结果可以看出使用 notify 线程按照我们设定的 C->A->B 的顺序执行。 当我们把所有 notify 改成 notifyAll 会输出

线程 ID: 14, 线程名称: A
线程 ID: 16, 线程名称: C
线程 ID: 15, 线程名称: B
C: 0
A: 1
C: 2
B: 3
A: 4
C: 5
B: 6
A: 7
A 执行结束
C 执行结束
B: 8
B 执行结束

执行顺序会发生改变, 因为所有等待中的线程都被唤醒了。

三、join

join: 等待指定线程终止后继续运行。

例子

	NukixThread B = new NukixThread("B") {
			@Override
			public void run() {
				super.run();
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				System.out.println("B 执行结束");
			}
		};
		
		NukixThread A = new NukixThread("A") {
			@Override
			public void run() {
				super.run();
				
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				try {
					B.join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				System.out.println("A 执行结束");
			}
		};
		
		
		A.start();
		B.start();

输出

线程 ID: 15, 线程名称: A
线程 ID: 14, 线程名称: B
B 执行结束
A 执行结束

A 等待1秒, B 等待5秒, 正常情况应该 A 先结束。 但执行 B.join() 后, A 需要等到 B 执行完毕后才能继续执行。

四、setDaemon和isDaemon

setDaemon: 设置线程为守护线程。
isDaemon: 判断线程是否守护线程。

例子

	NukixThread B = new NukixThread("B") {
			@Override
			public void run() {
				super.run();
				for (int i = 0; i < 1000; i++) {
					System.out.println("B 执行中: " + i + ", isDaemon: " + isDaemon());
				}
				
				System.out.println("B 执行结束");
			}
		};
		
		NukixThread A = new NukixThread("A") {
			@Override
			public void run() {
				super.run();
				
				B.start();
				
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				System.out.println("A 执行结束");
			}
		};
		
		B.setDaemon(true);
		A.start();

输出

线程 ID: 15, 线程名称: A
线程 ID: 14, 线程名称: B
B 执行中: 0, isDaemon: true
B 执行中: 1, isDaemon: true
...
A 执行结束
...
B 执行中: 116, isDaemon: true

可以看出, B 正常情况应该输出 999 但输出到 116 就已经不输出, 而且也没有输出执行结束, 程序已经停止。 因为 B 设置为守护线程, 用户线程(main线程、A线程)已经停止, 所以 守护线程 B 被迫停止了。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nukix

如果觉得对你有帮助,欢迎打赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值