这是一个常见的笔试题,自己本身对多线程理解的不是很透彻,特此记录一下这种多线程面试题下面通过两种方式实现。
第一种方式通过Lock锁机制来实现:
package com.zte.st.dailybuild.controller;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by 6092002943 on 2019/7/23.
*/
public class ThreadTest1 {
int i = 0;
int zm = 65;
boolean flag = true;
private Lock lock = new ReentrantLock();
private Condition cd1 = lock.newCondition();
private Condition cd2 = lock.newCondition();
public void printNum() {
lock.lock();//上锁
try {
System.out.print("数字前 ");
while (!flag) {
cd1.await();//把当前线程阻塞挂起
System.out.print("数字wait后 ");
}
System.out.print("数字后 ");
System.out.print(++i);
System.out.print(++i);
flag = false;
cd2.signal();//唤醒阻塞的线程
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();//释放锁,必须在finally中去释放,避免死锁
}
}
public void printZIMU() {
lock.lock();
try {
System.out.print("ZIMU前 ");
while (flag) {
cd2.await();//阻塞
System.out.print("字母wait后 ");
}
System.out.print("ZIMU后 ") ;
flag = true;
System.out.print(Character.toChars(zm));
zm++;
cd1.signal();//唤醒阻塞线程
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ThreadTest1 test = new ThreadTest1();
new Thread(() -> {
for (int i = 0; i < 26; i++) {
test.printNum();
}
}, "AA").start();
new Thread(() -> {
for (int i = 0; i < 26; i++) {
test.printZIMU();
}
}, "BB").start();
}
}
运行结果:
12A34B56C78D910E1112F1314G1516H1718I1920J2122K2324L2526M2728N2930O3132P3334Q3536R3738S3940T4142U4344V4546W4748X4950Y5152Z
发现: cd2.signal(); 表示唤醒阻塞的线程,即回到await()方法阻塞之后接着执行,每个方法每次执行都会执行两次,这个两次指的是flag变化两次。
第二种使用wait、notify:
package com.zte.st.dailybuild.controller;
import org.springframework.context.event.GenericApplicationListener;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by 6092002943 on 2019/7/22.
*/
public class ThreadTest {
public static void main(String[] args) {
ThreadTest test = new ThreadTest();
new Thread(() -> {
for (int i = 0; i < 1; i++) {
test.writeChars();
}
}, "AA").start();
new Thread(() -> {
for (int i = 0; i < 1; i++) {
test.writeNums();
}
}, "BB").start();
}
private boolean flag = false;
public synchronized void writeNums() {
try {
for (int i = 1; i <= 26; ) {
System.out.print("数字前 ");
if (flag) {
System.out.print("数字wait前 ");
wait();
System.out.print("数字wait后 ");
} else {
System.out.print(i * 2 - 1);
System.out.print(i * 2);
flag = true;
i++;
this.notifyAll();
System.out.print("数字后 ");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void writeChars() {
try {
for (int i = 'A'; i <= 'Z'; ) {
System.out.print("字符前 ");
if (!flag) {
System.out.print("字符wait前 ");
wait();
System.out.print("字符wait后 ");
} else {
System.out.print((char) i);
flag = false;
i++;
this.notifyAll();
System.out.print("字符后 ");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果:和第一种结果是一样的!可以自己去试。
总结:好多家公司的笔试题都有这种类似的,特此记录一下,研究一下,基础横重要的。