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