-
启动三个线程,打印出ABC,但无序,可能是BCA,或者CBA等等。 -
启动三个线程,按照顺序打印出ABC,要确定每次运行都按这个顺序打印。 -
启用三个线程,按照顺序打印出ABC,不光要按照顺序打印,而且要连续打印20次,也就是ABCABC…这样的形式。
一、打印字符ABC,但无序
这个比较简单,三个线程各打印A、B、C,然后启动这些线程即可,当然,打印出来的字符就是没有顺序的了。代码如下:
package com.sample.interview.multithread;
// 三个线程打印字符ABC,但顺序不确定
public class PrintRandomly {
public static void main(String[] args) {
Thread threadA = new Thread(()-> System.out.print("A"));
Thread threadB = new Thread(()-> System.out.print("B"));
Thread threadC = new Thread(()-> System.out.print("C"));
threadA.start();
threadB.start();
threadC.start();
}
}
二、按顺序打印字符ABC
按顺序打印字符ABC,那我们就得控制这三个线程的执行顺序,线程A先执行,接下来是线程B,最后是线程C。针对类似的并发编程场景,Java提供了一个非常方便实用的类Semaphore,也就是信号量,可以将它看作一个“许可证”,通过它可以实现多线程对于公共资源的并发访问控制,一个线程在获取资源时需要先取得一个许可,否则会阻塞,资源使用完成后,再把许可放回去。
为了按顺序打印ABC,我们控制线程B必须在线程A执行之后再开始执行,线程C类似,所以我们定义三个信号量,初始的许可证数量都是0,因为数量都是0,所以调用信号量的acquire方法时会被阻塞,如果前面的线程执行完成,把许可证数量加1,后面的线程就可以执行了,这样,就实现了顺序打印的功能。
package com.sample.interview.multithread;
import java.util.concurrent.Semaphore;
// 多线程顺序打印出ABC
public class PrintSequentially {
public static void main(String[] args) {
Semaphore semaphoreA = new Semaphore(0);
Semaphore semaphoreB = new Semaphore(0);
Semaphore semaphoreC = new Semaphore(0);
Thread threadA = new Thread(() -> {
try {
semaphoreA.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("A");
semaphoreB.release();
});
Thread threadB = new Thread(() -> {
try {
semaphoreB.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("B");
semaphoreC.release();
});
Thread threadC = new Thread(() -> {
try {
semaphoreC.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("C");
semaphoreA.release();
});
// 线程A的许可证数量加1
semaphoreA.release();
threadC.start();
threadB.start();
threadA.start();
}
}
三、按顺序打印字符ABC20次
有了第二步的铺垫,要实现顺序打印字符ABC20次的功能就相对比较简单了,在每个线程里面直接循环20次即可。因为信号量的acquire方法会尝试去获取一个许可,如果没有就会阻塞,如果拿到了,就把信号量的许可减1,而release方法则是把许可加1,所以,如果前面的线程没有调用这个归还方法,后面的线程是会阻塞的,多次循环也就是简单地把这样的运作多次执行即可。我们把代码稍作提炼如下:
package com.sample.interview.multithread;
import java.util.concurrent.Semaphore;
// 循环打印ABC20次
public class PrintSequentiallyLoop {
public static void main(String[] args) {
Semaphore semaphoreA = new Semaphore(1);
Semaphore semaphoreB = new Semaphore(0);
Semaphore semaphoreC = new Semaphore(0);
PrintChar printCharA = new PrintChar(semaphoreA, semaphoreB,"A");
PrintChar printCharB = new PrintChar(semaphoreB, semaphoreC,"B");
PrintChar printCharC = new PrintChar(semaphoreC, semaphoreA,"C");
new Thread(printCharA).start();
new Thread(printCharB).start();
new Thread(printCharC).start();
}
static class PrintChar implements Runnable{
Semaphore cur;
Semaphore next;
private String str;
private int times = 20;
public PrintChar(Semaphore cur, Semaphore next, String str){
this.cur = cur;
this.next = next;
this.str = str;
}
@Override
public void run() {
for (int i = 0; i < times; i++) {
try {
cur.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(str);
next.release();
}
}
}
}
以上就是多线程顺序打印ABC20次的解决方案,前面也提过,有很多方法可以解决该问题,在当前案例中,我们使用在信号量Semaphore作为并发控制的手段,它的功能强大,使用简单,也便于记忆,后续如果碰到类似的面试题目,我想,只要认真读完本文,是一定能够给出答案的。
都看到这里了,请帮忙一键三连啊,也就是点击文末的在看、点赞、分享,这样会让我的文章让更多人看到,也会大大地激励我进行更多的输出,谢谢!
推荐阅读:
原文始发于微信公众号(互联网全栈架构):高频面试题:多线程顺序打印ABC字符20次
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/173659.html