如何控制多线程执行顺序

摘要:
所以在线程1之后。如果调用join(),mainThread将被阻止。

现象

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

免责声明:文章转载自《如何控制多线程执行顺序》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇最小环——Floyd变种算法(C++)图解ARP协议(五)免费ARP:地址冲突了肿么办?下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

jvm主内存与工作内存

一、jvm主内存与工作内存     首先,JVM将内存组织为主内存和工作内存两个部分。     主内存主要包括本地方法区和堆。每个线程都有一个工作内存,工作内存中主要包括两个部分,一个是属于该线程私有的栈和对主存部分变量拷贝的寄存器(包括程序计数器PC和cup工作的高速缓存区)。   1.所有的变量都存储在主内存中(虚拟机内存的一部分),对于所有线程都是共...

进程与线程(2)- python实现多进程

python实现多进程 参考链接:https://morvanzhou.github.io/tutorials/python-basic/multiprocessing/ python中实现多进程的模块:multiprocessing 注意:在windows系统下,要想启动一个子进程,必须把进程相关的内容写在”if __name__ == “__main...

Android JNI 学习(十一):Invocation Api

1. 简介 Invocation API允许软件提供商在原生程序中内嵌Java虚拟机。因此可以不需要链接任何Java虚拟机代码来提供Java-enabled的应用程序。 以下代码演示如何使用: #include <jni.h> /* where everything is defined */ //......

python 异常处理、进程

目录: 异常处理 python进程 python并发之多进程 一、异常处理(try...except...) 1、程序中难免出现错误,而错误分成两种: a.语法错误: View Code b.逻辑错误(逻辑错误) View Code 2、异常定义:异常就是程序运行时发生错误的信号。 在python中,错误触发的异常,是以异常追踪信息、异常类型、异常值三...

Java并发编程-多线程

1、进程与线程   一个程序就是一个进程,一个程序中的多个任务被称为线程。进程是资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位。多线程的好处并发执行提高了程序的效率,CPU不会因为某个线程需要等待资源而进入空闲状态 2、线程的实现方式 继承java.lang.Thread类 实现java.lang.Runnable接口,然后交...

JAVA多线程提高八:线程锁技术

前面我们讲到了synchronized;那么这节就来将lock的功效。 一、locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---AbstractOwnableSynchronizer |---AbstractQueuedLongSynchronizer |---AbstractQueued...