美文网首页Android开发收藏夹Android开发Android知识
Java线程等待、睡眠、停止(wait、join、yield、I

Java线程等待、睡眠、停止(wait、join、yield、I

作者: HuDP | 来源:发表于2016-06-25 12:14 被阅读1648次
    1. wait、notify机制通常用于等待机制的实现,调用wait进入等待状态,需要的时候调用notify或notifyAll唤醒等待的线程继续执行;wait会释放对象锁。(wait()、notify()、notifyAll()必须放在synchronized block中)
     public static void waitAndNotifyAll() {
            System.out.println("主线程运行");
            Thread thread = new WaitThread();
            thread.start();
            long startTime = System.currentTimeMillis();
            try {
                synchronized (sLockObject) {
                    System.out.println("主线程等待");
                    sLockObject.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long timeMs = System.currentTimeMillis() - startTime;
            System.out.println("等待耗时:" + timeMs);
        }
    
        static class WaitThread extends Thread {
            @Override
            public void run() {
                super.run();
                System.out.println("子线程正在运行... " + Thread.currentThread().getName());
                synchronized (sLockObject) {
                    try {
                        Thread.sleep(3000);
                        sLockObject.notifyAll();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    waitAndNotifyAll函数中sLockObject的wait函数使得主线程进入了等待状态,WaitThread的run函数睡眠了3秒钟后调用了sLockObject的notifyAll函数,此时正在等待的主线程就会被唤醒。
    注:wait方法配合while循环(循环条件控制是否真的唤醒)使用可以避免notify以及notifyAll的错误唤醒,是正确以及推荐的做法。


    wait执行日志.png
    1. Thread的静态函数sleep()是用于实现线程睡眠的,sleep()不会释放对象锁。

    2. 上面的部分十分直观,join的作用就不那么直观了;join函数的意思是阻塞当前调用join函数所在的线程,直到接收线程执行完毕之后再继续。

    /**
         * join()
         * 阻塞当前调用join函数时所在的线程
         * 直到接收到线程执行完毕之后再继续
         */
        private void initJoin() {
            WaitThread waitThread1 = new WaitThread();
            WaitThread waitThread2 = new WaitThread();
    
            waitThread1.start();
            System.out.println("启动线程1");
            try {
                // 调用waitThread1线程的join函数,主线程会阻塞到waitThread1执行完成
                waitThread1.join();
                System.out.println("启动线程2");
                waitThread2.start();
                // 调用waitThread2线程的join函数,主线程会阻塞到waitThread2执行完成
                waitThread2.join();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("主线程继续执行");
        }
    //--------------------
     class WaitThread extends Thread {
            @Override
            public void run() {
                super.run();
                System.out.println("子线程正在运行... " + Thread.currentThread().getName());
                synchronized (sLockObject) {
                    try {
                        Thread.sleep(3000);
                        sLockObject.notifyAll();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    上面的逻辑为,启动线程1等待线程1执行完成、启动线程2、等待线程2执行完成、继续执行主线程的代码。


    join执行日志.png
    1. yield()作用是主动让出当前线程的执行权,其他线程能否优先执行就看各个线程的状态了。

    2. 当一个线程运行时,另一个线程调用该线程的interrupt()方法来中断他,注意interrupt方法只是在目标线程中设置一个标志,表示线程已经中断,需要注意如果只单纯调用interrupt方法,线程是不会中断的,应该这样:

    public class StopRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("StopRunnable 开始...");
            try {
                Thread.sleep(10000);
                System.out.println("StopRunnable try中..."); 
            } catch (InterruptedException e) {
                e.printStackTrace();
                //处理完中断异常后,返回到run()方法入口
                System.out.println("StopRunnable 强制停止...");
                //如果没有return,线程不会实际被中断,它会继续打印下面的信息 
                return;
            }
            System.out.println("StopRunnable 结束...");
        }
    }
    

    调用目标线程的interrup方法后,目标线程就会抛InterruptedException异常,捕获到异常后return,利用异常+return的方式实现了线程的停止。

    interrup执行日志.png

    参考资料:

    1. Android开发进阶 从小工到专家
    2. https://github.com/GeniusVJR/LearningNotes/blob/master/Part2/JavaConcurrent/线程中断.md

    有蛮久没更新文章了,最近一直在忙自己的事情,欢迎各位小伙伴一起讨论。

    相关文章

      网友评论

        本文标题:Java线程等待、睡眠、停止(wait、join、yield、I

        本文链接:https://www.haomeiwen.com/subject/gdhadttx.html