美文网首页
谈谈Java中线程的执行顺序

谈谈Java中线程的执行顺序

作者: 雨果是程序员 | 来源:发表于2019-08-01 01:01 被阅读0次

    线程执行顺序

    我们先来看一个简单的例子,我们显示地创建三个线程t1、t2、t3,按照声明的顺序,依次分别调用线程的start方法,线程的执行顺序是怎样的?程序执行的结果会如何?:

    public class ThreadOrderDemo {
        // 显示地创建三个线程,观察执行顺序
        static Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("This is thread1");
            }
        });
        static Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("This is thread2");
            }
        });
        static Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("This is thread3");
            }
        });
        public static void main(String[] args) throws Exception {
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

    猜测程序执行结果:
    1.按照代码顺序执行,依次为t1、t2、t3:

    This is thread1
    This is thread2
    This is thread3
    

    2.按照CPU调度规则,顺序随机:

    This is thread1
    This is thread3
    This is thread2
    

    我们经过编辑器执行,会发现结果是2,按照CPU调度,执行顺序随机。
    那我们如何让线程有序执行呢?以下有两种方式。

    方式一:使用join让主线程等待

    public static void main(String[] args) throws Exception {
            // 方式一:使用join让主线程等待
            t1.start();
            t1.join();
    
            t2.start();
            t2.join();
            
            t3.start();
        }
    

    上述改写主线程main方法,使用Thread类提供的join方法,可以达到让线程有序执行的效果。

    public final synchronized void join(long millis)
        throws InterruptedException {
            long base = System.currentTimeMillis();
            long now = 0;
    
            if (millis < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
    
            if (millis == 0) {
                while (isAlive()) {
                    wait(0);
                }
            } else {
                while (isAlive()) {
                    long delay = millis - now;
                    if (delay <= 0) {
                        break;
                    }
                    wait(delay);
                    now = System.currentTimeMillis() - base;
                }
            }
        }
    

    查看Thread类源码,可知,此处join方法,实质上是通过调用Object的wait方法,让主线程等待子线程执行,子线程执行完之后,主线程再执行。

    方式二:使用线程池队列

    public class ThreadOrderDemo {
        // 显示地创建三个线程,观察执行顺序
        static Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("This is thread1");
            }
        });
        static Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("This is thread2");
            }
        });
        static Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("This is thread3");
            }
        });
        static ExecutorService executor = Executors.newSingleThreadExecutor();
      
        public static void main(String[] args) throws Exception {
            // 方式二:使用线程池队列
           executor.submit(t1);
           executor.submit(t2);
           executor.submit(t3);
        }
    }
    

    上述使用J.U.C(java.util.concurrent)包中的ExecutorService建立线程池队列,以保持线程有序执行。

    public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
    
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), defaultHandler);
        }
    

    序号 参数名 类型 含义
    1 corePoolSize int 核心线程池大小
    2 maximumPoolSize int 最大线程池大小
    3 keepAliveTime long 线程最大空闲时间
    4 unit TimeUnit 时间单位
    5 workQueue BlockingQueue<Runnable> 线程等待队列
    6 threadFactory ThreadFactory 线程创建工厂
    7 handler RejectedExecutionHandler 拒绝策略

    上述Executors.newSingleThreadExecutor()实质是LinkedBlockingQueue,创建了一个阻塞的安全线程队列,FIFO先进先出,所以可以达到线程有序执行的目的。

    推荐阅读

    谈谈Java中hashCode和equals方法
    谈谈Java中==和equals到底有啥区别
    从月薪5千到月薪3万,优秀的程序员

    相关文章

      网友评论

          本文标题:谈谈Java中线程的执行顺序

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