问题引出
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); }