线程任务之线程中断、线程等待、线程睡眠

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenbetter1996/article/details/87303292

1. 线程中断

  Thread类提供了一种线程可以中断其他线程的机制。当一个线程被中断时,它会抛出java.lang.InterruptedException异常。这一机制由下面三种方法构成。

一个线程在未正常结束之前, 被强制终止是很危险的. 因为它可能带来完全预料不到的严重后果. 也因此Thread.suspend, Thread.stop等方法都弃用了。那么不能直接把一个线程搞挂掉, 但有时候又有必要让一个线程死掉, 或者让它结束某种等待的状态,优雅的方法就是, 给那个线程一个中断信号, 让它自己决定该怎么办

  • void interrupt(): 中断调用此方法的Thread对象所关联的线程。

当一条线程由于调用了Thread的sleep()或者join()方法而被阻塞时,该线程的中断状态就会被清除,同时抛出InterruptedException异常。

  • static boolean interrupted(): 验证当前线程是否已经中断,这个方法会清除掉线程的中断状态
  • boolean isInterrupted(): 也是验证当前线程是否已经中断,但是不会清除中断状态
public class InterruptThread {
	public static void main(String[] args) throws InterruptedException {
		Runnable r = () -> {
	        // 中断当前线程
			Thread.currentThread().interrupt();
			// isInterrupted()方法不会清除中断状态
			System.out.println(Thread.currentThread().isInterrupted());
			// interrupted()方法是静态类方法,会清除中断状态
			System.out.println(Thread.currentThread().interrupted());
			System.out.println(Thread.currentThread().interrupted());
		};
		
		Thread t1 = new Thread(r, "t1");
		t1.start();
	}
}
# 结果显然如下
true
true
false

2. 线程等待

  线程(如main主线程)有时候会启动另一个线程去操作单调的计算、下载文件等耗时操作。而调用工作的线程(如主线程)又需要等待这个工作线程执行结束,以处理其得到的结果(如计算结果)。
  Thread类提供了3种重载join()方法,允许调用线程等待执行此方法的线程对象所关联的线程执行完毕。(即其他线程(如主线程)要等待调用了join方法的工作线程执行结束)

  • void join(): 其他要无限期等待,直到调用该方法的线程死亡。当任意线程中断该线程的时候,会抛出InterruptedException,这个异常被抛出
  • void join(long millis): 该线程死亡之前,其他最多等待millis毫秒。参数取负数抛出IllegalArgumentException异常,此外join(0) <=> join()。
  • void join(long millis, int nanos): 要最多等待毫秒+纳秒。
public class JoinDemo {
	private static int count = 0;
	
	public static void main(String[] args) {
		Runnable r = () -> { 
			System.out.println("处理工作线程的业务");
			count ++;
		};
		Thread t1 = new Thread(r, "t1");
		t1.start();
	
		try {
			t1.join();
		} catch (InterruptedException e) {
			// 当这条工作线程被其他线程中断就会抛出InterruptedException异常
			e.printStackTrace();
		}
		
		System.out.println("主线程等待工作线程结束然后处理结果: " + count);
	}
}

调用了t1.join(),主线程要等待t1运行结束打印结果如下,也就是串行顺序执行。

处理工作线程的业务
主线程等待工作线程结束然后处理结果: 1

如果去掉。那么t1和主线程就会并发执行,结果基本都如下(t1线程从NEW状态到就绪的时候,系统调度主线程,然后才到t1线程获取到CPU资源执行run()方法的业务)

主线程等待工作线程结束然后处理结果: 0
处理工作线程的业务

3. 线程睡眠

  Thread类声明了一对静态重载使线程休眠的方法。(暂时性地停止执行)。

  • void sleep(long millies): 睡眠millis毫秒数。线程睡眠实际的毫秒数取决于系统定时器和调试器的精度。如果millis是负数,那么就会导致IllegalArgumentException被抛出。当任意线程中断了当前线程,就会导致InterruptedException被抛出,异常抛出,线程的中断状态就会被清除。
  • void sleep(long millis, int nanos): 毫秒+纳秒。

sleep()方法相较于忙循环更好,因为它们不会浪处理器周期。

public class SleepDemo {

	public static void main(String[] args) {
		Runnable r = () -> {
			String name = Thread.currentThread().getName();
			int count = 0;
			while (!Thread.interrupted()) {
				System.out.println(name + ":" + count++);
			}
			
		};
		
		Thread t1 = new Thread(r, "t1");
		Thread t2 = new Thread(r, "t2");
		t1.start();
		t2.start();
		
		try {
			// 当前线程睡眠1millis
			Thread.sleep(1);
		} catch (InterruptedException e) {
			//
		}
		t1.interrupt();
		t2.interrupt();
	}
}

主线程休眠1millis,t1和t2线程此时并发执行。结果的多少取决于系统。

t1:0
t1:1
t1:2
t1:3
t1:4
t1:5
t2:0
t1:6
t2:1
t1:7
t2:2
t1:8
...

猜你喜欢

转载自blog.csdn.net/chenbetter1996/article/details/87303292