Android中让多个线程顺序执行探究

本文深入探讨了线程调度的两种模型:分时调度与抢占式调度,并阐述了它们在多线程环境中的工作原理。接着,文章介绍了如何利用优先队列实现线程顺序执行,提供了示例代码,详细解释了优先队列的基本用法及其实现过程。最后,文章总结了如何通过优先级、join()方法、Thread.sleep()和Thread.yield()方法来控制线程执行顺序。

线程调度是指按照特定机制为多个线程分配CPU的使用权。
有两种调度模型:分时调度模型和抢占式调度模型。  
分时调度模型:是指让所有的线程轮流获得cpu的使用权,并且平均分配每个线程占用的CPU的时间片。
抢占式调度模型:是指优先让可运行池中优先级高的线程占用CPU,如果可运行池中的线程优先级相同,那么就随机选择一个线程,使其占用CPU。处于运行状态的线程会一直运行,直至它不得不放弃CPU。一个线程会因为以下原因而放弃CPU:
1 、java虚拟机让当前线程暂时放弃CPU,转到就绪状态,使其它线程或者运行机会。
2、 当前线程因为某些原因而进入阻塞状态
3、 线程结束运行
需要注意的是,线程的调度不是跨平台的,它不仅仅取决于java虚拟机,还依赖于操作系统。在某些操作系统中,只要运行中的线程没有遇到阻塞,就不会放弃CPU;在某些操作系统中,即使线程没有遇到阻塞,也会运行一段时间后放弃CPU,给其它线程运行的机会,java的线程调度是不分时的,同时启动多个线程后,不能保证各个线程轮流获得均等的CPU时间片。如果希望明确地让一个线程给另外一个线程运行的机会,可以采取以下办法之一:调整各个线程的优先级、让处于运行状态的线程调用、Thread.sleep()方法、让处于运行状态的线程调用Thread.yield()方法、让处于运行状态的线程调用另一个线程的join()方法

所以,让多个线程顺序执行有三个确切的办法:
1、改变线程的优先级(不同的系统上可能并不会按照优先级来执行)
2、调用join()方法,一个线程在run中调用join()方法时,会阻塞当前线程,而让新加入的线程执行完再执行本线程
3、第三个方法是我自己想出来的,就是使用PriorityQueue优先队列,PriorityQueue有这样一个特征,就是可以让队列中某个优先级最高元素最先出来,所以利用这个特性,可以让我们想要哪个线程先执行就先执行,最后通过线程的State来判断该线程是否执行完毕,再执行下一个线程,这个方法的一个好处是各线程之间不必使用join来执行了,各个线程可以独立出来。

PriorityQueue的用法:

PriorityQueue<Integer> queue = new PriorityQueue<Integer>(11, new MyComparator());
        queue.add(3);
        queue.add(1);
        queue.add(-2);
        queue.add(4);
        queue.add(6);
        queue.add(9);
        queue.add(2);
        queue.offer(8);
        while (!queue.isEmpty()) {
            Log.v("zxy", queue.poll() + "");//9864321-2
        }
public static class MyComparator implements Serializable, Comparator<Integer> {

        @Override
        public int compare(Integer lhs, Integer rhs) {
            int value = lhs > rhs ? 1 : lhs < rhs ? -1 : 0;
            return value;
        }
    }

上面这个示例就是优先队列的基本用法,它可以传入一个我们自定义的比较器,利用这个比较器我们可以自己定义队列中元素的顺序。其中compare()方法中的返回值:
1、>0:代表lhs>rhs
2、<0:代表rhs>lhs
3、==0:代表lhs==rhs

而PriorityQueue中有这么几个方法:
1、queue.poll():表示从队列中取出队首上的元素,且取出后remove掉这个元素
2、queue.peek():表示从队列中取出队首上的元素,且取出后不remove掉这个元素
3、queue.add():表示添加一个元素
4、queue.clear():表示清空队列
5、queue.remove():表示移除某个元素
6、queue.size():表示队列的size

利用优先队列实现多个线程顺序执行

final PriorityQueue<Thread> queue = new PriorityQueue<>(11, new MyThreadComparator());
        queue.add(thread1);
        queue.add(thread2);
        queue.add(thread3);
        queue.add(thread5);
        queue.add(thread7);
        queue.add(thread6);
        queue.add(thread4);
        boolean flag = false;
        Thread mThread = null;
        int i=0;
        int size = queue.size();
        while (!queue.isEmpty()) {
            if(!flag){
                mThread = queue.poll();
                mThread.start();
                flag = true;
                i++;
            }
            if(mThread.getState()== Thread.State.TERMINATED && !queue.isEmpty()){
                if(size==i){
                    break;
                }
                if(size==(i+1)){
                    mThread = queue.peek();
                    mThread.start();
                    i++;
                }else {
                    mThread = queue.poll();
                    mThread.start();
                    i++;
                }
            }
        }
public static class MyThreadComparator implements Serializable, Comparator<Thread> {

        @Override
        public int compare(Thread lhs, Thread rhs) {
            int value = lhs.getPriority() < rhs.getPriority() ? 1 : lhs.getPriority() > rhs.getPriority() ? -1 : 0;
            return value;
        }
    }

这里每创建一个线程我都给它设置了一个自带的优先级(其实这个只是一个标志,你也可以用任何东西作为标志,比如采用),用来表示该线程的优先级:

Thread thread1 = new Thread( new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.v("zxy", "result—>thread1");
            }
        });
        thread1.setPriority(3);

利用它做的一些效果:

这里写图片描述这里写图片描述
这里写图片描述这里写图片描述
这里写图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值