• 如何控制多线程执行顺序


    现象

    public class Test02 {
        static Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread1");
            }
        });
    
        static Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread2");
            }
        });
    
        static Thread thread3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread3");
            }
        });
    
        public static void main(String[] args) {
            thread1.start();
            thread2.start();
            thread3.start();
        }
    }
    

    上面的代码执行结果:

    // 线程执行顺序是随机的
    thread1
    thread3
    thread2
    

    原因:start()方法只是让子线程处于就绪状态,最终执行状态是不可控的

    解决方案

    方案一:使用join控制多线程执行顺序

    join():让主线程等待子线程结束以后才能继续运行

    public static void main(String[] args) throws Exception {
    	thread1.start();
    	thread1.join();  // 让主线程放弃cpu执行权,让给子线程执行
    	thread2.start();
    	thread2.join();
    	thread3.start();
    }
    

    结果:

    thread1
    thread2
    thread3
    

    join方法的原理就是调用相应线程的wait方法进行等待操作的,例如A线程中调用了B线程的join方法,则相当于在A线程中调用了B线程的wait方法,当B线程执行完(或者到达等待时间),B线程会自动调用自身的notifyAll( 调用了JVM底层lock.notify_all(thread)方法来唤醒 )方法唤醒A线程,从而达到同步的目的

    jion()源码:

    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;
    		}
    	}
    }
    

    最终是调用object的wait方法

    public final native void wait(long timeout) throws InterruptedException;
    

    join()的调用位于main Thread的main()中,所以这里当然就是阻塞main Thread了。所以thread1.join()调用后,main Thread会阻塞起来。

    方案二:利用单线程化线程池(newSingleThreadExecutor)串行执行所有任务

    利用并发包里的ExcutorsnewSingleThreadExecuto产生一个单线程的线程池,而这个线程池的底层原理就是一个先进先出(FIFO)的队列。代码中executor.submit依次添加了123线程,按照FIFO的特性,执行顺序也就是123的执行结果,从而保证了执行顺序

    static ExecutorService executorService = Executors.newSingleThreadExecutor();
    public static void main(String[] args) throws Exception {
    	executorService.submit(thread1);
    	executorService.submit(thread2);
    	executorService.submit(thread3);
    	executorService.shutdown();
    }
    
  • 相关阅读:
    第3次作业卷积神经网络
    SpringCloud Sidecar 整合.Net WebApi
    redefinition of class解决
    DP学习笔记
    NOIP2018 Day2毒瘤题目
    NOIP Day1总结
    关于DP
    这次的PION的总结
    NOIP模拟赛D2T1自己的解题思路
    ABAP Editor自动完成功能
  • 原文地址:https://www.cnblogs.com/tian-ci/p/10543076.html
Copyright © 2020-2023  润新知