美文网首页
Android多线程(三)——线程控制

Android多线程(三)——线程控制

作者: 何小送 | 来源:发表于2020-05-05 01:23 被阅读0次

    前言:这里讲的线程都不采用线程池,继承Thread类和实现Runnable以及Callable都通过Thread来创建并启动,即这里的线程控制都是指Thread的方法

    线程控制(即Thread类)主要有5个方法

    • join线程:join()
    • 后台线程:setDaemon()
    • 线程睡眠:sleep()
    • 线程让步:yield()
    • 改变线程优先级:setPriority()

    一. join线程

    join线程指:让一个线程等待另一个线程完成。
    1. join():等待线程执行完成
    当在A线程中调用B线程的join()方法时,调用线程(A线程)将被阻塞,直到B线程执行完为止。
    2. join(long millis):等待被join的线程最长时间为millis毫秒
    在A线程里调用B线程的join(long millis)方法,A将被阻塞,阻塞时间不超过millis。假如B线程需要10*1000毫秒才执行完毕,而millis为5000,那么B执行5秒后,A和B都回到就绪状态
    3. join(long millis,int nanos): 等待被join的线程最长时间为millis毫秒+nanos毫微秒
    该方法忽略不用

    public class JoinCallable implements Callable {
        private int i=0;
        @Override
        public Object call() throws Exception {
            for (;i<5;i++){
                Log.d("MainActivity",Thread.currentThread().getName()+" i:"+i);
                Thread.sleep(100);
            }
            return null;
        }
    }
    //使用
        private void joinCallable() {
            
            try {
                for (int i=0;i<6;i++){
                    Log.d("MainActivity",Thread.currentThread().getName()+":"+i);
                    if (i==3){
                        Callable joinCallable = new JoinCallable();
                        FutureTask task = new FutureTask(joinCallable);
                        Thread thread = new Thread(task, "join线程");
                        thread.start();
                        thread.join();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    //运行打印日志
    2020-05-04 22:49:24.264 31878-31878/priv.hsj.thread D/MainActivity: main:0
    2020-05-04 22:49:24.265 31878-31878/priv.hsj.thread D/MainActivity: main:1
    2020-05-04 22:49:24.265 31878-31878/priv.hsj.thread D/MainActivity: main:2
    2020-05-04 22:49:24.265 31878-31878/priv.hsj.thread D/MainActivity: main:3
    2020-05-04 22:49:24.267 31878-31914/priv.hsj.thread D/MainActivity: join线程 i:0
    2020-05-04 22:49:24.368 31878-31914/priv.hsj.thread D/MainActivity: join线程 i:1
    2020-05-04 22:49:24.469 31878-31914/priv.hsj.thread D/MainActivity: join线程 i:2
    2020-05-04 22:49:24.569 31878-31914/priv.hsj.thread D/MainActivity: join线程 i:3
    2020-05-04 22:49:24.671 31878-31914/priv.hsj.thread D/MainActivity: join线程 i:4
    2020-05-04 22:49:24.777 31878-31878/priv.hsj.thread D/MainActivity: main:4
    2020-05-04 22:49:24.777 31878-31878/priv.hsj.thread D/MainActivity: main:5
    
    

    注意:join方法必须要在start方法后调用才有效

    二. 后台线程

    后台线程是在后台运行的,为其他的线程提供服务,他也叫”守护线程“和”精灵线程🧚‍♀️“。
    JVM的垃圾回收线程就是典型的后台线程。
    如果所有的前台线程都死亡,后台线程就会自动死亡。
    Thread类还提供了isDaemon()方法,用于判断指定线程是否为后台线程。

    注意:setDaemon(true)必须必须要在start()方法前调用,否则会IllegalThreadStateException异常。

    三. 线程睡眠

    线程睡眠是让当前正在执行的线程暂停一段时间,即阻塞一段时间

    • sleep(long millis):让当前正在执行的线程暂停millis毫秒,并进入阻塞状态
    • sleep(long millis,int nanos):让当前正在执行的线程暂停millis毫秒加nanos毫微秒。该方法忽略不用。

    当前线程调用sleep()方法进入阻塞状态后,在其睡眠时间段内,该线程不会获得执行的机会,即使系统中没有其他可执行的线程,处于sleep()中的线程也不会执行。
    sleep()时间过完后,由阻塞状态转为就绪状态

    四. 线程让步

    线程让步是将线程转入就绪状态

    当前线程调用yield()方法进入就绪状态,线程调度器重新调度
    线程调用yield()方法后将执行机会让给优先级相同,或优先级更高的线程


    sleep()与yield方法区别

    1. sleep()是将线程转入阻塞状态。yield()是将该线程转入就绪状态
    2. sleep()期间,会给其他线程执行机会,其他所有线程机会平等,与优先级无关。yield()只会给优先级相同或优先级更高的线程执行机会,即有可能某个线程调用yield()方法暂停之后,会立即再次获得CPU
    3. sleep()方法声明抛出异常,而yield()没有声明抛出异常。
    4. sleep()比yield()有更好的可移植性,并发线程一般不会使用yield()

    五. 改变线程优先级

    每个线程执行时都具有一定的优先级,优先级高的线程获得较多的执行机会,优先级低的获得较少的执行机会。
    每个线程默认的优先级都与创建它的父线程的优先级相同。

    setPriority(int newPriority)方法参数取值范围为1~10,默认为5,Thread类给了三个静态常量

    • MAX_PRIORITY:值为10
    • MIN_PRIORITY:值为1
    • NORM_PRIORITY:值为5
      在开发中,尽量避免使用具体数字,应使用三个静态常量,这样更具有移植性。

    上一篇:Android多线程(二)——线程的生命周期:https://www.jianshu.com/p/0b9468cda0c7

    相关文章

      网友评论

          本文标题:Android多线程(三)——线程控制

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