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

前言:这里讲的线程都不采用线程池,继承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多线程(三)——线程控制)