面試題:常見的多執行緒實戰手撕程式碼(順序列印數字、字母)
阿新 • • 發佈:2018-12-12
問題一:
一個多執行緒的問題,用三個執行緒,順序列印字母A-Z,輸出結果是1A 2B 3C 1D 2E…列印完畢最後輸出一個Ok。
程式碼一:
public class forCharacter {
private static char c = 'A';
private static int i = 0;
public static void main(String[] args) throws InterruptedException {
Runnable r = new Runnable() {
public void run() {
int threadId = Integer.parseInt(Thread.currentThread().getName());
while(i < 26){
if(i % 3 == threadId - 1){
System.out.println("執行緒id:" + threadId + " " + (char)c++);
i++;
if (i == 26)
System.out.println("哈哈,祝拿到offer!");
}
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
};
Thread t1 = new Thread(r, "1");
Thread t2 = new Thread(r, "2");
Thread t3 = new Thread(r, "3");
t1.start();
t2.start();
t3.start();
}
}
但是程式碼一存在問題:這樣寫的話,可能會造成資源浪費,所以我們可以通過加鎖進行限制,但是加鎖後,因為sleep不會釋放鎖,會導致其他執行緒無法獲得執行機會。因此需要配合wait和notifyAll。
程式碼二:
public class forCharacter {
/*
* Description:一個多執行緒的問題,用三個執行緒,順序列印字母A-Z,輸出結果是1A 2B 3C 1D 2E...列印完畢最後輸出一個Ok
* Author:ZhangRuirui
* Date:2018/05/25
* Email:[email protected]
*/
private static char c = 'A';// 必要的時候宣告為volatile型別的
private static int i = 0;
public static void main(String[] args) throws InterruptedException {
Runnable r = new Runnable() {
public void run() {
synchronized (this) {
try {
int threadId = Integer.parseInt(Thread.currentThread().getName());
System.out.println("當前執行緒id:" + threadId + " ");
while (i < 26) {
if (i % 3 == threadId - 1) {
System.out.println("執行緒id:" + threadId + " " + (char) c++);
i++;
if (i == 26)
System.out.println("哈哈,祝拿到offer!");
notifyAll();// 喚醒其他執行緒
} else {
wait();// 阻塞其他執行緒
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t1 = new Thread(r, "1");
Thread t2 = new Thread(r, "2");
Thread t3 = new Thread(r, "3");
t1.start();
t2.start();
t3.start();
}
}
輸出:
當前執行緒id:1
執行緒id:1 A
當前執行緒id:2
執行緒id:2 B
當前執行緒id:3
執行緒id:3 C
執行緒id:1 D
執行緒id:2 E
執行緒id:3 F
執行緒id:1 G
執行緒id:2 H
執行緒id:3 I
執行緒id:1 J
執行緒id:2 K
執行緒id:3 L
執行緒id:1 M
執行緒id:2 N
執行緒id:3 O
執行緒id:1 P
執行緒id:2 Q
執行緒id:3 R
執行緒id:1 S
執行緒id:2 T
執行緒id:3 U
執行緒id:1 V
執行緒id:2 W
執行緒id:3 X
執行緒id:1 Y
執行緒id:2 Z
哈哈,祝拿到offer!
問題二:(快手)
一個多執行緒的問題,用五個執行緒,順序列印數字1~無窮大,其中每5個數字為1組,如下:其中id代表執行緒的id
id 1 2 3 4 5
no 1 2 3 4 5
no 6 7 8 9 10
no 11 12 13 14 15
no .. .. .. .. ..
程式碼:
public class forCharacter2 {
/*
* Description:一個多執行緒的問題,用五個執行緒,順序列印數字1~無窮大,其中每5個數字為1組
* Author:ZhangRuirui
* Date:2018/05/25
* Email:[email protected]
*/
private static volatile int orderNum = 1;// 必要的時候宣告為volatile型別的
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
synchronized (this) {
try {
int threadId = Integer.parseInt(Thread.currentThread().getName());
while (true) {
if (orderNum % 5 == threadId || orderNum % 5 == 0) {
if (orderNum % 5 == 0)
System.out.println("threadid = " + 5 + " " + orderNum++);
else
System.out.println("threadid = " + threadId + " " + orderNum++);
Thread.sleep(1000);// 為了執行效果看的更清楚
notifyAll();
} else {
wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t1 = new Thread(r, "1");
Thread t2 = new Thread(r, "2");
Thread t3 = new Thread(r, "3");
Thread t4 = new Thread(r, "4");
Thread t5 = new Thread(r, "5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
輸出:
threadid = 1 1
threadid = 2 2
threadid = 3 3
threadid = 4 4
threadid = 5 5
threadid = 1 6
threadid = 2 7
threadid = 3 8
threadid = 4 9
threadid = 5 10
threadid = 1 11
threadid = 2 12
threadid = 3 13
threadid = 4 14
threadid = 5 15
threadid = 1 16
threadid = 2 17
下面死迴圈不斷輸出
—–樂於分享,共同進步,歡迎補充
—–Any comments greatly appreciated
—–誠心歡迎各位交流討論!QQ:1138517609