标题【面试题】两个线程交互打印输出A1B2C3D4E5F6G7…23X24Y25Z26
方式一 使用synchronized结合WaitNotify实现
public class SolutionByWaitNotify {
public static void main(String[] args) throws Exception {
SolutionByWaitNotify solution = new SolutionByWaitNotify();
Thread t1 = new Thread(solution::printCharsByWaitNotify);
Thread t2 = new Thread(solution::printNumsByWaitNotify);
t1.start();
t2.start();
}
public synchronized void printCharsByWaitNotify(){
try{
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < str.length(); i++) {
System.out.print(str.charAt(i));
this.notify();//通知唤醒线程,但还没释放锁
this.wait();//释放锁
}
}catch (Exception e){e.printStackTrace();}
}
public synchronized void printNumsByWaitNotify(){
try{
for (int i = 0; i < 26; i++) {
System.out.print(i+1);
this.notify();//通知唤醒线程,但还没释放锁
this.wait();//释放锁
}
}catch (Exception e){e.printStackTrace();}
}
}
每次输出一条就wait,notify,两个线程交互睡眠,唤醒,实现交互输出
方式二 使用CAS锁实现
public class SolutionByCAS {
public static void main(String[] args) throws Exception {
SolutionByCAS solution = new SolutionByCAS();
Thread t1 = new Thread(solution::printCharsByCAS);
Thread t2 = new Thread(solution::printNumsByCAS);
t1.start();
t2.start();
}
AtomicInteger flag = new AtomicInteger(1); //使用java提供的CAS锁实现
public void printCharsByCAS() {
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < str.length(); i++) {
while (flag.get()!=1){}
System.out.print(str.charAt(i));
flag.set(0);
}
}
public void printNumsByCAS() {
for (int i = 0; i < 26; i++) {
while (flag.get()==1) {}
System.out.print(i+1);
flag.set(1);
}
}
}
使用的是AtomicInteger这个原子类。连个线程都一直死循环的判断flag是否==1,什么实话等于1了,输出一个数字,什么时候不等于1了输出一个字母。
由于AtomicInteger内部使用的是CAS锁,锁能够保证【可见性】和【原子性】,所以AtomicInteger的状态改变,对其他线程是可见的。
方式三 使用volatile关键字实现
public class SolutionByVolatile {
public static void main(String[] args) throws Exception {
SolutionByVolatile solution = new SolutionByVolatile();
Thread t1 = new Thread(solution::printCharsByVolatile);
Thread t2 = new Thread(solution::printNumsByVolatile);
t1.start();
t2.start();
}
volatile boolean flag = true;
public void printCharsByVolatile() {
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < str.length(); i++) {
while (!flag){}
System.out.print(str.charAt(i));
flag = false;
}
}
public void printNumsByVolatile() {
for (int i = 0; i < 26; i++) {
while (flag) {}
System.out.print(i+1);
flag = true;
}
}
}
和CAS类似,但是这个就没用用到锁,只是给flag加了volatile关键字,保证了flag在两个线程间可见。
方式四 使用一种搞笑得方式实现
public class SolutionByJoke {
public static void main(String[] args) throws Exception {
SolutionByJoke solution = new SolutionByJoke();
Thread t1 = new Thread(solution::printByJoke);
Thread t2 = new Thread(solution::printByJoke);
t1.start();
t2.start();
}
int count = 0;
public synchronized void printByJoke() {
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
while (count<52){
if (count%2==0){
System.out.print(str.charAt(count/2));
}else System.out.print((count / 2)+1);
count++;
}
}
}
最后这个是一个搞笑的方式,一本正经的假装没问题。虽然能输出正确的结果,但想想为啥是在搞笑 ~-_-