面试官:你说说如何让“线程”按序执行?
Posted 熬夜加班写代码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试官:你说说如何让“线程”按序执行?相关的知识,希望对你有一定的参考价值。
当线程处于就绪状态时,等待被分配到CPU时间片然后才真正开始执行,由于每个线程开始的时间不确定,因此也就不能唯一确定线程的执行顺序。如果想让线程有序执行,主要思路就是让子线程的执行在主线程中串行化,想到了以下几种让线程按顺序执行的方法
让线程按序执行的方法 JDK自带方法 join 等待线程执行终止的方法
可以在主线程中调用子线程的join()方法,让子线程按序执行,代码如下:
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1 do something");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t2 do something");
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t3 do something");
}
});
t1.start();
// 主线程阻塞等待子线程执行完
t1.join();
t2.start();
// 主线程阻塞等待子线程执行完
t2.join();
t3.start();
// 主线程阻塞等待子线程执行完
t2.join();
}
并发工具类
CountDownLatch
countDownLatch.await()会阻塞调用线程直到 state==0。因此,可以利用这个特性使得子线程按序执行
private static CountDownLatch countDownLatch = new CountDownLatch(1);
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1 do something");
countDownLatch.countDown();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t2 do something");
countDownLatch.countDown();
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t3 do something");
countDownLatch.countDown();
}
});
t1.start();
// 主线程阻塞等待子线程执行完毕
countDownLatch.await();
t2.start();
// 主线程阻塞等待子线程
countDownLatch.await();
t3.start();
// 主线程阻塞等待子线程
countDownLatch.await();
}
CycleBarrier
如下有三个任务,分三个步骤执行,依次按照线程123执行 barrier.await()方法,可以让当前线程等待其他线程执行完毕
static CyclicBarrier barrier = new CyclicBarrier(1, new Runnable() {
@Override
public void run() {
System.out.println("barrier" + Thread.currentThread().getName());
}
});
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("t1 do something");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t2 do something");
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t3 do something");
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t3.start();
}
信号量
分别依次打印ABC,循环10次
public class ABCSemaphore {
private static Semaphore A = new Semaphore(1);
private static Semaphore B = new Semaphore(1);
private static Semaphore C = new Semaphore(1);
static class ThreadA extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
A.acquire();
System.out.print("A");
B.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ThreadB extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 4; i++) {
B.acquire();
System.out.print("B");
C.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ThreadC extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 5; i++) {
C.acquire();
System.out.print("C");
A.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
// 开始只有A可以获取, BC都不可以获取, 保证了A最先执行
B.acquire();
C.acquire();
new ThreadA().start();
new ThreadB().start();
new ThreadC().start();
}
}
放入线程池按照顺序执行
线程池中有很多线程去处理任务,不能够保证执行顺序,如果线程池可串行化,那么放入的任务可顺序执行,记得把线程池的线程数设置为1
// 此处注意 线程数设置为1
ExecutorService service = Executors.newFixedThreadPool(1);
service.submit(new Runnable() {
@Override
public void run() {
System.out.println("child thread1 do something ");
}
});
service.submit(new Runnable() {
@Override
public void run() {
System.out.println("child thread2 do something ");
}
});
以上是关于面试官:你说说如何让“线程”按序执行?的主要内容,如果未能解决你的问题,请参考以下文章
新浪网面试官:说说Java并发编程中CountDownLatch原理与应用