Java多线程-Thread常用方法

sleep() 线程休眠

  • 使当前线程休眠,但不会释放对象的同步锁;

  • 运行状态 -> 休眠(阻塞状态);

  • 线程休眠的时间大于指定的休眠时间就会重新被唤醒,阻塞状态 -> 就绪状态,从而等待CPU的调度执行;

yield() 线程让步

  • 立即中止当前线程的执行,重新争夺CPU,但不会释放对象的同步锁(用在同步代码块中就没意义了);

  • 运行状态 -> 就绪状态;

  • 以便让其他具有相同优先级的等待线程获取执行权,也可能当前线又进入运行状态;

join() 线程合并

  • 将子线程的执行和父线程合并;

  • 父线程等待子线程执行结束才会继续执行;

下面是join()方法的源码:

    /**
     * Waits for this thread to die.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final void join() throws InterruptedException {
        join(0);
    }

第一句就表明,执行此方法,会等待此线程死亡,即是父线程等待子线程的死亡,或者被中断。
下面是未使用线程合并的程序:

    public class Demo {
        public static void main(String[] args) {
            ChildThread childThread = new ChildThread();
            childThread.start();
            System.out.println("主线程执行结束");
        }
    }
    
    class ChildThread extends Thread {
        @Override
        public void run() {
            System.out.println("子线程运行开始");
            try {
                sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("子线程运行结束");
        }
    }

其运行结果:

	主线程执行结束
	子线程运行开始
	子线程运行结束

可以看出主线程和子线程是并行执行的。

加入线程合并:

    ChildThread childThread = new ChildThread();
    childThread.start();
    try {
        System.out.println("并入主线程之前");
        childThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("主线程执行结束");

其运行结果:

	并入主线程之前
	子线程运行开始
	子线程运行结束
	主线程执行结束

最初,子线程和主线程都确实是并行执行的,但当主线程执行到childThread.join(),如果子线程还未结束,则会等待子线程结束,然后才会继续执行主线程。

interrupt() 线程中断

stop()方法和suspend()也可用于线程中断,但这两个方法已在1.2版本被废弃了。

中止处于阻塞状态的线程

当线程由于被调用了sleep()、wait()、join()、等方法而进入阻塞状态;若此时调用线程的interrput()线程的中断标记设为true。由于处于阻塞状态,中断标记会被清除(设为false),同时产生一个InterruptedException异常。通过捕获该异常来中断阻塞线程

    @Override
    public void run() {
        try {
            while (true) {
                // 执行任务...
            }
        } catch (InterruptedException ie) {  
            // 由于产生InterruptedException异常,退出while(true)循环,线程终止!
        }
    }
    @Override
    public void run() {
        while (true) {
            try {
                // 执行任务...
            } catch (InterruptedException ie) {  
                // InterruptedException在while(true)循环体内。
                // 当线程产生了InterruptedException异常时,while(true)仍能继续运行!需要手动退出
                break;
            }
        }
    }
中止处于运行状态的线程
  • 中断标记:
	@Override
	public void run() {
		while (!isInterrupted()) {
			// 执行任务...
		}
	}

调用interrrupt()会使isInterrupted()返回true,常用来中断处于阻塞状态的线程。

  • 额外添加标记:
	@Override
	public void run() {
		try {
			while (true) {
				// 执行任务...
			}
		} catch (InterruptedException ie) {  
			// 由于产生InterruptedException异常,退出while(true)循环,线程终止!
		}
	}

综合中断线程阻塞状态和运行状态的方式,以下是比较通用的线程中断方式:

    @Override
    public void run() {
        try {
            // 1. isInterrupted()保证,只要中断标记为true就终止线程。
            while (!isInterrupted()) {
                // 执行任务...
            }
        } catch (InterruptedException ie) {  
            // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。
        }
    }

实例:

    public class Demo {
        public static void main(String[] args) throws InterruptedException {
            MyThread myThread = new MyThread();
            myThread.start();
            // 确保子线程先处于阻塞状态
            Thread.sleep(1000);
            System.out.println("中断子线程");
            myThread.interrupt();
        }
    }
    
    class MyThread extends Thread {
        @Override
        public void run() {
            try {
                while (!isInterrupted()) {
                    System.out.println("子线程阻塞");
                    sleep(4000);
                }
            } catch (InterruptedException e) {
                System.out.println("子线程捕获到中断异常");
                
            }
        }
    }

执行结果:

	子线程阻塞
	中断子线程
	子线程捕获到中断异常

如果把try{}catch(){}放在while内的执行结果:

	子线程阻塞
	中断子线程
	子线程捕获到中断异常
	子线程阻塞
	子线程阻塞
	子线程阻塞
	......

结果造成了死循环。

interrupted()和isInterrupted()

相同点:两者都能用于检测对象的中断标记

不同点:

  • interupted()除了返回中断标记,还会清除中断标记(将中断标记设为false);

  • isInterrupted()仅仅返回中断标记;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值