如何控制多線程執行順序

問題引出
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);
}


發佈了39 篇原創文章 · 獲贊 8 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章