创建 n 个线程,循环打印 m 次(a-z,A-Z,大小写间隔输出)
多线程面试编程题:创建n个线程,循环打印m次(a-z,A-Z,大小写间隔输出)
参考链接:记一个Java多线程相关的面试题 https://www.1024sou.com/article/228174.html
例如:3个线程,打印2次(a-z,A-Z) 输出结果 thread1-a,thread2-A,thread3-b。。。。循环两次。
大概意思就是创建指定数量n的线程循环打印m次,循环内容是线程依次交错执行,分别从两个共享资源交错取数据。
这道题确实一开始写不出来,于是就遵从简单到复杂一个个写出来,然后优化升级。
本题默认使用 3 个线程来轮流打印字母,多线程轮流打印使用 Semaphore 这个并发工具类合适,因此本题使用 Semaphore 进行多线程并发控制。
最简单的解法:N 个线程打印 a-z 区间,只循环1次
public class ThreadInterleaving {
private static final int N = 3;
private static int count = 0;
private static char a = 'a';
private static Semaphore[] semaphores = new Semaphore[N];
public static void main(String[] args) {
try {
new ThreadInterleaving().testAZTaskBasic();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void testAZTaskBasic() throws InterruptedException {
for (int i = 0; i < N; i++) {
semaphores[i] = new Semaphore(1);//只能被任意线程持有一次,释放之后才能被其他线程持有
if (i > 0) semaphores[i].acquire();//除第0个线程对应的 Semaphore,其余都先被主线程持有
}
for (int i = 0; i < N; i++) {
Semaphore cur = semaphores[i];
Semaphore next = i == N - 1 ? semaphores[0] : semaphores[i + 1];
new Thread(new AZTaskBasic(cur, next), "Thread" + i + ":").start();
}
}
/**
* 首先写出最简单的解法:N 个线程打印 a-z 区间,只循环1次
* Thread0:a
* Thread1:b
* Thread2:c
* Thread0:d
* Thread1:e
* Thread2:f
*/
static class AZTaskBasic implements Runnable {
private final Semaphore curSemaphore;
private final Semaphore nextSemaphore;
public AZTaskBasic(Semaphore curSemaphore, Semaphore nextSemaphore) {
this.curSemaphore = curSemaphore;
this.nextSemaphore = nextSemaphore;
}
@Override
public void run() {
while (true) {
try {
curSemaphore.acquire();
if (count >= 26) break;
System.out.println(Thread.currentThread().getName() + (char) (a + count++));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
nextSemaphore.release();
}
}
}
}
}
打印结果:
Thread0:a
Thread1:b
Thread2:c
Thread0:d
Thread1:e
Thread2:f
Thread0:g
Thread1:h
Thread2:i
Thread0:j
Thread1:k
Thread2:l
Thread0:m
Thread1:n
Thread2:o
Thread0:p
Thread1:q
Thread2:r
Thread0:s
Thread1:t
Thread2:u
Thread0:v
Thread1:w
Thread2:x
Thread0:y
Thread1:z
最简单的解法2:N 个线程打印 a-z 区间,循环2次
public class ThreadInterleaving {
private static final int N = 3;
private static int count = 0;
private static char a = 'a';
private static Semaphore[] semaphores = new Semaphore[N];
public static void main(String[] args) {
try {
new ThreadInterleaving().testAZTaskBasicPrintTwice();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void testAZTaskBasicPrintTwice() throws InterruptedException {
for (int i = 0; i < N; i++) {
semaphores[i] = new Semaphore(1);
if (i > 0) semaphores[i].acquire();
}
for (int i = 0; i < N; i++) {
Semaphore cur = semaphores[i];
Semaphore next = i == N - 1 ? semaphores[0] : semaphores[i + 1];
new Thread(new AZTaskBasicPrintTwice(cur, next), "Thread" + i + ":").start();
}
}
/**
* 最简单的解法2:N 个线程打印 a-z 区间,循环2次
*/
static class AZTaskBasicPrintTwice implements Runnable {
private final Semaphore curSemaphore;
private final Semaphore nextSemaphore;
public AZTaskBasicPrintTwice(Semaphore curSemaphore, Semaphore nextSemaphore) {
this.curSemaphore = curSemaphore;
this.nextSemaphore = nextSemaphore;
}
@Override
public void run() {
while (true) {
try {
curSemaphore.acquire();
if (count >= 26) {
time++;
if (time >= REPEAT_TIME) break;
count = 0;
}
System.out.println(Thread.currentThread().getName() + (char) (a + count++));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
nextSemaphore.release();
}
}
}
}
}
打印结果:
Thread0:a
Thread1:b
Thread2:c
Thread0:d
Thread1:e
Thread2:f
Thread0:g
Thread1:h
Thread2:i
Thread0:j
Thread1:k
Thread2:l
Thread0:m
Thread1:n
Thread2:o
Thread0:p
Thread1:q
Thread2:r
Thread0:s
Thread1:t
Thread2:u
Thread0:v
Thread1:w
Thread2:x
Thread0:y
Thread1:z
Thread2:a
Thread0:b
Thread1:c
Thread2:d
Thread0:e
Thread1:f
Thread2:g
Thread0:h
Thread1:i
Thread2:j
Thread0:k
Thread1:l
Thread2:m
Thread0:n
Thread1:o
Thread2:p
Thread0:q
Thread1:r
Thread2:s
Thread0:t
Thread1:u
Thread2:v
Thread0:w
Thread1:x
Thread2:y
Thread0:z
初级:N 个线程打印 aBcDeFg..yZ 大小写间隔输出,只循环一次
public class ThreadInterleaving {
private static final int N = 3;
private static int count = 0;
private static char a = 'a';
private static Semaphore[] semaphores = new Semaphore[N];
public static void main(String[] args) {
try {
new ThreadInterleaving().testAZTaskLowerHigherCase();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void testAZTaskLowerHigherCase() throws InterruptedException {
for (int i = 0; i < N; i++) {
semaphores[i] = new Semaphore(1);
if (i > 0) semaphores[i].acquire();
}
for (int i = 0; i < N; i++) {
Semaphore cur = semaphores[i];
Semaphore next = i == N - 1 ? semaphores[0] : semaphores[i + 1];
new Thread(new AZTaskLowerHigherCase(cur, next), "Thread" + i + ":").start();
}
}
/**
* 初级:N 个线程打印 aBcDeFg..yZ 大小写间隔输出,只循环一次
*/
static class AZTaskLowerHigherCase implements Runnable {
private final Semaphore curSemaphore;
private final Semaphore nextSemaphore;
public AZTaskLowerHigherCase(Semaphore curSemaphore, Semaphore nextSemaphore) {
this.curSemaphore = curSemaphore;
this.nextSemaphore = nextSemaphore;
}
@Override
public void run() {
while (true) {
try {
curSemaphore.acquire();
if (count >= 26) break;
if (count % 2 == 0) {
System.out.println(Thread.currentThread().getName() + (char) (a + count));
} else {
System.out.println(Thread.currentThread().getName() + (char) (A + count));
}
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
nextSemaphore.release();
}
}
}
}
}
打印结果:
Thread0:a
Thread1:B
Thread2:c
Thread0:D
Thread1:e
Thread2:F
Thread0:g
Thread1:H
Thread2:i
Thread0:J
Thread1:k
Thread2:L
Thread0:m
Thread1:N
Thread2:o
Thread0:P
Thread1:q
Thread2:R
Thread0:s
Thread1:T
Thread2:u
Thread0:V
Thread1:w
Thread2:X
Thread0:y
Thread1:Z
最终解:打印 aA..zZ 大小写间隔输出, 循环2次
即:创建 n 个线程,循环打印 m 次(a-z,A-Z,大小写间隔输出)
public class ThreadInterleaving {
private static final int N = 3;
private static final int REPEAT_TIME = 2;
private static int time = 0;
private static int count = 0;
private static final int MAX_LETTER_COUNT_PER_ROUND = 26 * 2;
private static char A = 'A';
private static char a = 'a';
private static int lowerCaseIndex = 0;
private static int higherCaseIndex = 0;
private static Semaphore[] semaphores = new Semaphore[N];
public static void main(String[] args) {
try {
new ThreadInterleaving().testAZTask();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void testAZTask() throws InterruptedException {
for (int i = 0; i < N; i++) {
semaphores[i] = new Semaphore(1);
if (i > 0) semaphores[i].acquire();
}
for (int i = 0; i < N; i++) {
Semaphore cur = semaphores[i];
Semaphore next = i == N - 1 ? semaphores[0] : semaphores[i + 1];
new Thread(new AZTask(cur, next), "Thread" + i + ":").start();
}
}
/**
* 打印 aA..zZ 大小写间隔输出, 循环2次
*/
static class AZTask implements Runnable {
private final Semaphore curSemaphore;
private final Semaphore nextSemaphore;
public AZTask(Semaphore curSemaphore, Semaphore nextSemaphore) {
this.curSemaphore = curSemaphore;
this.nextSemaphore = nextSemaphore;
}
@Override
public void run() {
while (true) {
try {
curSemaphore.acquire();
if (count >= MAX_LETTER_COUNT_PER_ROUND) {
time++;
if (time >= REPEAT_TIME) break;
count = 0;
lowerCaseIndex = 0;
higherCaseIndex = 0;
}
if (count % 2 == 0) {
System.out.println(Thread.currentThread().getName() + (char) (a + lowerCaseIndex++));
} else {
System.out.println(Thread.currentThread().getName() + (char) (A + higherCaseIndex++));
}
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
nextSemaphore.release();
}
}
}
}
}
打印结果:
Thread0:a
Thread1:A
Thread2:b
Thread0:B
Thread1:c
Thread2:C
Thread0:d
Thread1:D
Thread2:e
Thread0:E
Thread1:f
Thread2:F
Thread0:g
Thread1:G
Thread2:h
Thread0:H
Thread1:i
Thread2:I
Thread0:j
Thread1:J
Thread2:k
Thread0:K
Thread1:l
Thread2:L
Thread0:m
Thread1:M
Thread2:n
Thread0:N
Thread1:o
Thread2:O
Thread0:p
Thread1:P
Thread2:q
Thread0:Q
Thread1:r
Thread2:R
Thread0:s
Thread1:S
Thread2:t
Thread0:T
Thread1:u
Thread2:U
Thread0:v
Thread1:V
Thread2:w
Thread0:W
Thread1:x
Thread2:X
Thread0:y
Thread1:Y
Thread2:z
Thread0:Z
Thread1:a
Thread2:A
Thread0:b
Thread1:B
Thread2:c
Thread0:C
Thread1:d
Thread2:D
Thread0:e
Thread1:E
Thread2:f
Thread0:F
Thread1:g
Thread2:G
Thread0:h
Thread1:H
Thread2:i
Thread0:I
Thread1:j
Thread2:J
Thread0:k
Thread1:K
Thread2:l
Thread0:L
Thread1:m
Thread2:M
Thread0:n
Thread1:N
Thread2:o
Thread0:O
Thread1:p
Thread2:P
Thread0:q
Thread1:Q
Thread2:r
Thread0:R
Thread1:s
Thread2:S
Thread0:t
Thread1:T
Thread2:u
Thread0:U
Thread1:v
Thread2:V
Thread0:w
Thread1:W
Thread2:x
Thread0:X
Thread1:y
Thread2:Y
Thread0:z
Thread1:Z
转载自:https://juejin.cn/post/7063423120895377422