如何控制多线程执行顺序

问题引出
public class Main {
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先执行,thread2在执行...


解决方法1:
join方法 -------> 保证多线程的顺序性
public static void main(String[] args) throws Exception{
thread1 .start();
thread1 .join();

thread2 .start();
thread2 .join();

thread3 .start();
}


join的作用:让主线程的等待子线程执行完后再执行
主线程会放弃主线程的执行权





源码分析

/**
* Waits for this thread to die. 一直等到这个线程终结
*
* <p> An invocation of this method behaves in exactly the same
* way as the invocation
*
* <blockquote>
* { @linkplain #join(long) join}{ @code (0)}
* </blockquote>
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i> interrupted status </i> of the current thread is
* cleared when this exception is thrown.
*/
public final void join() throws InterruptedException {
join( 0 );
}

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会阻塞起来。
那么main Thread被阻塞后是在哪收到notify而继续运行的呢?你可能在源码中找不到是哪notify了。 
其实,这个过程涉及到了JVM底层了。 thread1线程执行完毕了exit过程会有一个notifyall操作

在网上找的jvm源码:


1.java.lang.Thread.join方法通过循环阻塞主线程的方式保证当前线程优先执
2.当前线程执行完之后会立马唤醒主线程继续执行 注意 lock.notify_all(thread)


解决方法二:
static ExecutorService executorService = Executors. newSingleThreadExecutor (); //FIFO

public static void main(String[] args) throws Exception{
executorService .submit( thread1 );
executorService .submit( thread2 );
executorService .submit( thread3 );
executorService .shutdown();
}


查看源码

public interface ExecutorService extends Executor {
/**
 * An {@link Executor} that provides methods to manage termination and
 * methods that can produce a {@link Future} for tracking progress of
 * one or more asynchronous tasks.
ExecutorService是Executor的一种增强,提供了一些管理方法, 
包括终止Executor(可能是多个线程)、获得代表任务执行进度的Future。


/**
 * Creates an Executor that uses a single worker thread operating
 * off an unbounded queue. (Note however that if this single
 * thread terminates due to a failure during execution prior to
 * shutdown, a new one will take its place if needed to execute
 * subsequent tasks.)  Tasks are guaranteed to execute
 * sequentially, and no more than one task will be active at any
 * given time. Unlike the otherwise equivalent
 * {@code newFixedThreadPool(1)} the returned executor is
 * guaranteed not to be reconfigurable to use additional threads.
 *
 * @return the newly created single-threaded Executor
 */
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);
}


猜你喜欢

转载自blog.csdn.net/xinyeshuaiqi/article/details/80674995