主要内容
- 本文主要记录多线程相关的操作问题,这些问题主要出现在一些面试中,当然学会了对本身的代码能力也有提升。
目录
本文源码
系列文章
1
、
交
替
多
线
程
\color{7f1A8A}1、交替多线程
1、交替多线程
- 题目描述:两个线程,一个存有数组1、2、3和另一个存有a、b、c,然后通过调度,最终结果输出1a2b3c
- 设计思路:通过在while循环中加入判断,依次输出
- 主要源码
public class demo01 {
static volatile boolean flag = false;
static String[] array_alpha = {"A", "B", "C"};
static int[] array_num = {1, 2, 3};
public static void main(String[] args) {
Thread t_alpha = new Thread() {
int count = 0;
@Override
public void run() {
while (count < array_alpha.length) {
if (flag) {
System.out.print(array_alpha[count] + " ");
count++;
flag = !flag;
}
}
}
};
Thread t_num = new Thread() {
int count = 0;
@Override
public void run() {
while (count < array_num.length) {
if (!flag) {
System.out.print(array_num[count] + " ");
count++;
flag = !flag;
}
}
}
};
t_alpha.start();
t_num.start();
}
}
2
、
发
令
枪
问
题
\color{7f1A8A}2、发令枪问题
2、发令枪问题
- 题目描述:百米赛跑,4名运动员选手到达场地等待裁判口令,裁判一声口令,选手听到后同时起跑,当所有选手到达终点,裁判进行汇总排名
- 设计思路:使用CountDownLatch来实现统一。
- 主要源码
public class demo02 {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CountDownLatch cdOrder = new CountDownLatch(1);
final CountDownLatch cdAnswer = new CountDownLatch(4);
for (int i = 0; i < 4; i++) {
Runnable runnable = new Runnable() {
@SneakyThrows
@Override
public void run() {
System.out.println("选手" + Thread.currentThread().getName() + "正在等待裁判发布口令");
cdOrder.await();
System.out.println("选手" + Thread.currentThread().getName() + "已接受裁判口令");
Thread.sleep((long) (Math.random() * 3_000));
System.out.println("选手" + Thread.currentThread().getName() + "到达终点");
cdAnswer.countDown();
}
};
service.execute(runnable);
}
try {
Thread.sleep((long) (Math.random() * 3_000));
System.out.println("裁判" + Thread.currentThread().getName() + "即将发布口令");
cdOrder.countDown();
System.out.println("裁判" + Thread.currentThread().getName() + "已发送口令,正在等待所有选手到达终点");
cdAnswer.await();
System.out.println("所有选手都到达终点");
System.out.println("裁判" + Thread.currentThread().getName() + "汇总成绩排名");
} catch (InterruptedException e) {
e.printStackTrace();
}
service.shutdown();
}
}
3
、
多
线
程
顺
序
执
行
\color{7f1A8A}3、多线程顺序执行
3、多线程顺序执行
- 题目描述:现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
- 设计思路:使用Join实现线程顺序执行
- 主要源码
public class demo03 extends Thread{
public demo03(String name){
setName(name);
}
@SneakyThrows
@Override
public void run() {
Thread.sleep(1_000);
System.out.println("i am "+ this.currentThread().getName());
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new demo03("t1");
Thread t2 = new demo03("t2");
Thread t3 = new demo03("t3");
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
}
}
4
、
关
于
饥
饿
死
锁
\color{7f1A8A}4、关于饥饿死锁
4、关于饥饿死锁
public class ljtest{
private static ExecutorService executorService = Executors.newSingleThreadExecutor();
static class t1 implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("i am t1");
return "t1===";
}
}
static class t2 implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("i am t2");
Future<String> submit = executorService.submit(new t1());
return "t2===" + submit.get();
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
t2 t = new t2();
Future<String> submit = executorService.submit(t);
System.out.println(submit.get());
System.out.println("la~la~la~");
executorService.shutdown();
}
}
i am t2
i am t1
t2===t1===
la~la~la~
i am t2
- 原因分析
- 我们用到的线程池是Executors.newSingleThreadExecutor();他是只有一个线程的线程池。
- 当我们把t2放进去执行的时候,t2又把t1放进去了,这个时候t1在等t2结束,t2在等t1的返回值,出现饥饿等待。
5
、
线
程
数
设
置
为
多
少
合
适
?
\color{7f1A8A}5、线程数设置为多少合适?
5、线程数设置为多少合适?
- 题目:线程数设置为多少合适
- 理论上,单核CPU一直工作的话,只能处理一个线程。如果该线程一半时间在处理数据,一半时间在等IO,那么这个单核CPU可以处理两个线程。
- 因此类推出:
- 确定机器是几核的:n核
- 确定该线程的工作状态:有1/k的时间在处理计算,那么每核CPU可以处理k个线程。
- 结论:该机器线程数设置的合适数量是:(n*k)个线程