概述
文章目录
- 一、join方法
- 二、线程池
昨天做笔试题的时候遇到一个多线程的问题,需要我们创建三个线程,操作同一个String,并且依次赋值,最后打印。
操作同一个String只需要我们同步或者加锁就可以保证其原子性了,可是如何保证顺序执行呢?
一、join方法
我们来看api文档中的说明,等待本线程死亡。
也就是说,我们在其他线程run方法内部调用本线程的join方法,其他线程必须等待本线程死亡后才能继续执行后续的逻辑代码块。
public final void join()
throws InterruptedException
Waits for this thread to die.
An invocation of this method behaves in exactly the same way as the invocation
join(0)
Throws:
InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
所以我们可以这么写:
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.print(Thread.currentThread().getName() + " 1 ");
}catch (Exception e){
}
}
},"_A");
//lambda
final Thread t2 = new Thread(() -> {
try {
t1.join();
System.out.print(Thread.currentThread().getName() + " 2 ");
}catch (Exception e){
}
},"_B");
//lambda
final Thread t3 = new Thread(() -> {
try {
t2.join();
System.out.print(Thread.currentThread().getName() + " 3 ");
}catch (Exception e){
}
},"_C");
t1.run();
t2.run();
t3.run();
因为是在main方法里执行,所以打印出来的是main.
二、线程池
我们可以利用单线程线程池:
ExecutorService es =Executors.newSingleThreadExecutor();
es.submit(t1);
es.submit(t2);
es.submit(t3);
if(!es.isShutdown()){
es.shutdown();
}
这段逻辑是如何实现顺序执行的呢?
我们先来欣赏一下源码:
/**
* 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>()));
}
首先线程池的工作线程是单线程的,线程池维护了一个阻塞队列,队列中线程都出于休眠状态。工作线程会每次只会调出一个线程来执行,当当前线程的run()执行完并顺利结束后,线程池工作线程会继续从队列中取出一个线程并唤醒notify()。当队列为空时,线程池不会结束,而是会会等待队列中出现新的线程。当我们需要结束线程池时需要调用shutdown()方法。
注意,当我们保证顺序执行时,牺牲了并行性。
参考资料:
https://docs.oracle.com/javase/7/docs/api/index.html?index-filesindex-1.html
https://www.cnblogs.com/MOBIN/p/5436482.html
https://blog.csdn.net/eene894777/article/details/74942485
最后
以上就是疯狂溪流为你收集整理的创建三个线程并依次执行的全部内容,希望文章能够帮你解决创建三个线程并依次执行所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复