zoukankan      html  css  js  c++  java
  • 多线程学习-基础(四)常用函数说明:sleep-join-yield

    一、常用函数的使用

    (1)Thread.sleep(long millis):在指定的毫秒内让当前正在执行的线程休眠(暂停执行),休眠时不会释放当前所持有的对象的锁。
    (2)join():主线程等待子线程终止后才可以终止
         使用方式:
                join()是Thread的一个方法,启动线程后可以直接调用,即join()的作用是:“等待该线程终止”,这里需要解释的是“该线程终止”是指主线程等待子线程的终止。  

      Thread t = new AThread();
      t.start();
      t.join();

    为什么要用join()方法:

    在很多情况下,主线程生成并启动了子线程,如果子线程要进行大量的耗时运算,主线程往往在子线程之前结束,但是如果主线程处理完其他事务后,需要用到子线程的处理结果,也就是说主线程需要等待子线程结束之后才可以结束,这个时候就需要用到join()方法了。

    测试案例:

    不加join()方法

    package com.jason.comfuns.join;
    /**
     * 多线程学习
     * @function  不使用Thread.join()方法:测试在主线程中启动子线程时:主子线程的执行顺序
     * @author 小风微凉
     * @time  2018-4-21 下午12:56:31
     */
    public class Thread_join_Action extends Thread {
        private String thname;
        public Thread_join_Action(String name){
            super(name);
            this.thname=name;
        }
        public void run(){
            System.out.println(Thread.currentThread().getName()+"线程运行开始!");
            for(int i=0;i<5;i++){
                System.out.println("子线程"+thname+"运行:"+i);
                try {
                    sleep((int)Math.random()*10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"线程运行结束!");
        }
        /**
         * 启动测试程序
         * @param args
         */
        public static void main(String[] args) {
            System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
            Thread_join_Action thread1=new Thread_join_Action("A");
            Thread_join_Action thread2=new Thread_join_Action("B");
            thread1.start();
            thread2.start();
            System.out.println(Thread.currentThread().getName()+"主线程运行结束!");
        }
    }

    运行结果:(主线程:main在子线程A和子线程B之前结束了

    main主线程运行开始!
    main主线程运行结束!
    A线程运行开始!
    子线程A运行:0
    B线程运行开始!
    子线程B运行:0
    子线程A运行:1
    子线程B运行:1
    子线程A运行:2
    子线程B运行:2
    子线程A运行:3
    子线程B运行:3
    子线程A运行:4
    子线程B运行:4
    A线程运行结束!
    B线程运行结束!

    加入join():(所有子线程都调用join()
    测试案例:

    package com.jason.comfuns.join;
    /**
     * 多线程学习
     * @function  不使用Thread.join()方法:测试在主线程中启动子线程时:主子线程的执行顺序
     * @author 小风微凉
     * @time  2018-4-21 下午12:56:31
     */
    public class Thread_join_Action extends Thread {
        private String thname;
        public Thread_join_Action(String name){
            super(name);
            this.thname=name;
        }
        public void run(){
            System.out.println(Thread.currentThread().getName()+"线程运行开始!");
            for(int i=0;i<5;i++){
                System.out.println("子线程"+thname+"运行:"+i);
                try {
                    sleep((int)Math.random()*10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"线程运行结束!");
        }
        /**
         * 启动测试程序
         * @param args
         */
        public static void main(String[] args) {
            System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
            Thread_join_Action thread1=new Thread_join_Action("A");
            Thread_join_Action thread2=new Thread_join_Action("B");
            thread1.start();
            thread2.start();
            //开始调用子线程thread1的join()
            try {
                thread1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //开始调用子线程thread2的join()
            try {
                thread2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"主线程运行结束!");
        }
    }

    运行结果:

    执行结果:(主线程main,在子线程A和子线程B执行结束之后,才结束,前提:子线程A和子线程B都必须调用join()
    main主线程运行开始!
    A线程运行开始!
    B线程运行开始!
    子线程B运行:0
    子线程A运行:0
    子线程B运行:1
    子线程A运行:1
    子线程B运行:2
    子线程B运行:3
    子线程A运行:2
    子线程B运行:4
    子线程A运行:3
    B线程运行结束!
    子线程A运行:4
    A线程运行结束!
    main主线程运行结束!

    加入join():(部分子线程都调用join()
    测试案例:

    package com.jason.comfuns.join;
    /**
     * 多线程学习
     * @function  不使用Thread.join()方法:测试在主线程中启动子线程时:主子线程的执行顺序
     * @author 小风微凉
     * @time  2018-4-21 下午12:56:31
     */
    public class Thread_join_Action extends Thread {
        private String thname;
        public Thread_join_Action(String name){
            super(name);
            this.thname=name;
        }
        public void run(){
            System.out.println(Thread.currentThread().getName()+"线程运行开始!");
            for(int i=0;i<5;i++){
                System.out.println("子线程"+thname+"运行:"+i);
                try {
                    sleep((int)Math.random()*10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"线程运行结束!");
        }
        /**
         * 启动测试程序
         * @param args
         */
        public static void main(String[] args) {
    System.out.println(Thread.currentThread().getName()+"主程序运行开始!");
            Thread_join_Action thread1=new Thread_join_Action("A");
            Thread_join_Action thread2=new Thread_join_Action("B");
            thread1.start();
            thread2.start();
            //开始调用子线程thread1的join()------只有子线程A调用join()
            try {
                thread1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    System.out.println(Thread.currentThread().getName()+"主程序运行结束!");
    }
    }

    运行结果:只有在主线程中的调用了join()方法的子线程运行结束,主线程才会结束,没有调用join()方法的子线程不在此列

    main主程序运行开始!
    B线程运行开始!
    A线程运行开始!
    子线程A运行:0
    子线程B运行:0
    子线程A运行:1
    子线程B运行:1
    子线程A运行:2
    子线程B运行:2
    子线程A运行:3
    子线程B运行:3
    子线程A运行:4
    子线程B运行:4
    A线程运行结束!
    main主程序运行结束!
    B线程运行结束!

    (3)yield():暂停当前正在执行的线程,并执行其他线程。 

    Thread.yield():暂停当前正在执行的线程,并执行其他线程。
    yield()方法应该做的是让当前行线程回到可运行状态(就绪状态),以允许其他相同优先级或更高优先级的线程获得运行机会。因此,使用yield()方法的目的是让相同优先级的线程之间能够适当的轮转执行。但是,实际上无法保证yield()达到让步目的,因为让步线程(yield()的调用对象线程)还有可能被线程调度程序再次选中。

    结论:
    yield()从未导致:线程转到等待、休眠、阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态(就绪状态),但是有可能没效果。

     简单案例: (测试2个同优先级别的线程:在调用yield()方法时的执行情况

    package com.jason.comfuns.yield;
    /**
     * 多线程学习
     * @function  
     * @author 小风微凉
     * @time  2018-4-21 下午1:53:37
     * 总结:
     *     当一个线程调用yield(),那么当前运行线程会让出cpu执行权限,供自己其他同优先级别活更高的优先级别的线程抢夺。
     * 谁(线程)抢到,谁开始运行。
     */
    public class Thread_yield_Action extends Thread{
        private String thname;
        public Thread_yield_Action(String name){
            super(name);
            this.thname=name;
        }
        public void run(){
            System.out.println(Thread.currentThread().getName()+"线程运行开始");
            for(int i=0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+"线程运行:"+i);
                if(i==5){//当i为5时,该线程会让出CPU的执行机会,让其他或自己的线程执行。(简单来说:谁抢到CPU的权限谁执行)
                    System.out.println(Thread.currentThread().getName()+"让出CPU权限-------------");
                    Thread.yield();//或者this.yield()
                }
            }    
            System.out.println(Thread.currentThread().getName()+"线程运行结束");
        }
        public static void main(String[] args) {
            Thread_yield_Action thread1=new Thread_yield_Action("A");
            Thread_yield_Action thread2=new Thread_yield_Action("B");
            thread1.start();
            thread2.start();
        }
    }

     运行结果:

    运行结果:(当一个线程执行yield()后就让出cpu执行权限,供其他同优先级或自己的线程竞争抢夺)
    B线程运行开始
    A线程运行开始
    A线程运行:0
    A线程运行:1
    A线程运行:2
    B线程运行:0
    A线程运行:3
    A线程运行:4
    A线程运行:5
    A让出CPU权限-------------
    B线程运行:1
    B线程运行:2
    B线程运行:3
    B线程运行:4
    B线程运行:5
    A线程运行:6
    A线程运行:7
    A线程运行:8
    A线程运行:9
    B让出CPU权限-------------
    A线程运行结束
    B线程运行:6
    B线程运行:7
    B线程运行:8
    B线程运行:9
    B线程运行结束

     简单案例:(测试:2个线程,一个优先级10 , 一个优先级5,让优先级10的线程主动让出CPU的执行权限,检测执行情况

    package com.jason.comfuns.yield;
    /**
     * 多线程学习
     * @function 测试: yield()方法
     * @author 小风微凉
     * @time  2018-4-21 下午1:53:37
     * 总结:
     *     当一个线程调用yield(),那么当前运行线程会让出cpu执行权限,供自己其他同优先级别活更高的优先级别的线程抢夺。
     * 谁(线程)抢到,谁开始运行。
     */
    public class Thread_yield_Action extends Thread{
        private String thname;
        public Thread_yield_Action(String name){
            super(name);
            this.thname=name;
        }
        public void run(){
            System.out.println(Thread.currentThread().getName()+"线程运行开始");
            for(int i=0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+"线程运行:"+i);
                if(i==5){//当i为5时,该线程会让出CPU的执行机会,让其他或自己的线程执行。(简单来说:谁抢到CPU的权限谁执行)            
                    if("A".equals(Thread.currentThread().getName())){//如果是优先级大的则yield执行一次退让
                        System.out.println(Thread.currentThread().getName()+"让出CPU权限-------------");
                        Thread.yield();//或者this.yield()
                    }                
                }
            }    
            System.out.println(Thread.currentThread().getName()+"线程运行结束");
        }
        public static void main(String[] args) {
            Thread_yield_Action thread1=new Thread_yield_Action("A");
            Thread_yield_Action thread2=new Thread_yield_Action("B");
            thread1.setPriority(MAX_PRIORITY);//优先级:10
            thread1.start();
            thread2.setPriority(MIN_PRIORITY);//优先级:5
            thread2.start();
        }
    }

    运行结果:(总结:A的优先级为10级,B的优先级为5级,即使A的线程调用了yield()方法,让出了cpu的执行权,从执行状态退到了可执行状态,但是由于目前之后线程A和线程B,还是会优先调度线程A

    A线程运行开始
    A线程运行:0
    A线程运行:1
    A线程运行:2
    B线程运行开始
    A线程运行:3
    A线程运行:4
    A线程运行:5
    A让出CPU权限-------------
    B线程运行:0
    A线程运行:6
    A线程运行:7
    A线程运行:8
    A线程运行:9
    A线程运行结束
    B线程运行:1
    B线程运行:2
    B线程运行:3
    B线程运行:4
    B线程运行:5
    B线程运行:6
    B线程运行:7
    B线程运行:8
    B线程运行:9
    B线程运行结束

     简单案例:(测试:2个线程,一个优先级10 , 一个优先级5,让优先级5的线程主动让出CPU的执行权限,检测执行情况

    修改上面部分代码:

    public static void main(String[] args) {
            Thread_yield_Action thread1=new Thread_yield_Action("A");
            Thread_yield_Action thread2=new Thread_yield_Action("B");
            Thread_yield_Action thread3=new Thread_yield_Action("C");
            thread1.setPriority(MIN_PRIORITY);//5级
            thread1.start();
            thread2.setPriority(MAX_PRIORITY);//10级
            thread2.start();
            thread3.setPriority(2);//2级
            thread3.start();
        }

    运行结果:(总结:A的优先级为5级,B的优先级为10级,此时由于B的优先级高于A,B已经先行执行完毕了,然后A的线程调用了yield()方法,让出了cpu的执行权,此时只剩下A线程和C线程,由于A线程优先级别高于C线程,则仍然会优先执行A线程,最后C线程

    B线程运行开始
    B线程运行:0
    B线程运行:1
    B线程运行:2
    B线程运行:3
    B线程运行:4
    B线程运行:5
    B线程运行:6
    B线程运行:7
    B线程运行:8
    B线程运行:9
    B线程运行结束
    A线程运行开始
    A线程运行:0
    A线程运行:1
    A线程运行:2
    A线程运行:3
    A线程运行:4
    A线程运行:5
    A让出CPU权限-------------
    A线程运行:6
    A线程运行:7
    A线程运行:8
    A线程运行:9
    A线程运行结束
    C线程运行开始
    C线程运行:0
    C线程运行:1
    C线程运行:2
    C线程运行:3
    C线程运行:4
    C线程运行:5
    C线程运行:6
    C线程运行:7
    C线程运行:8
    C线程运行:9
    C线程运行结束

  • 相关阅读:
    Unity3D-实现连续点击两次返回键退出游戏(安卓/IOS)
    Unity3D插件-自制小插件、简化代码便于使用(新手至高手进阶必经之路)
    Unity3D安卓程序中提示窗与常用静态方法封装
    Unity插件-NGUI使用教程
    Unity 3D游戏-塔防类游戏源码:重要方法和功能的实现
    Unity 3D编辑器扩展介绍、教程(二) —— 创建窗口
    Unity 3D编辑器扩展介绍、教程(一) —— 创建菜单项
    Unity 3D换装系统教程/Demo
    Unity3D游戏-愤怒的小鸟游戏源码和教程(二)
    WebApi接口测试
  • 原文地址:https://www.cnblogs.com/newwind/p/8902108.html
Copyright © 2011-2022 走看看