一道经典的多线程面试题:
两个线程,一个线程打印1-26,另一个线程打印A-Z,但是需要的效果是两个线程交替打印,产生效果如1A2B………26Z的效果。
- 思考:这个其实考察了两个线程间的通信问题。
思路如下:需要实现两个线程,重写run方法,run方法内部需要26次for循环,分别打印数字和字母,但是需要线程1(打印1)阻塞,切换到线程2(打印A)阻塞,切换到线程1(打印2)……
- 方法一,使用synchronized解决:
package demo;
/**
* 循环打印1A2B……
* @author Gxp
*
*/
public class A1B2_syn {
// 定义一个锁
static Object lock = new Object();
// 定义两个线程
static Thread number = new Thread(()->{
// 线程内部方法需要加synchronized,锁定lock对象
synchronized (lock) {
for (int i = 1; i < 27; i++) {
System.out.print(i);
// 打印出一个后,先唤醒其他线程
lock.notifyAll();
try {
// 阻塞当前线程,并且释放锁,这里判断是最后的边界条件,最后一次输出当前线程就不需要阻塞了
if (i != 25) {
lock.wait();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
static Thread letter = new Thread(()->{
synchronized (lock) {
for (int i = 0; i < 26; i++) {
System.out.print((char)('A'+i));
lock.notifyAll();
try {
// 这里一定要判断边界条件,假如是最后一个输出,则不需要阻塞,直接结束就好了,否则该线程会一直阻塞
if (i != 25) {
lock.wait();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
public static void main(String[] args) {
number.start();
// 保证线程letter线程先运行
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
letter.start();
}
}
- 方法二:通过Lock和Conditon实现
package demo;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 循环打印1A2B…… 使用lock实现
* @author Gxp
*
*/
public class A1B2_lock {
static Lock lock = new ReentrantLock();
static Condition letter = lock.newCondition();
static Condition number = lock.newCondition();
static Thread numberThread = new Thread(()->{
try {
lock.lock();
for (int i = 0; i < 26; i++) {
System.out.print(i+1);
// 需要先唤醒letter线程
letter.signal();
// 然后再阻塞自己
if (i != 25) {
number.await();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
});
static Thread letterThread = new Thread(()->{
try {
lock.lock();
for (int i = 0; i < 26; i++) {
System.out.print((char)('A'+i));
number.signal();
if (i != 25) {
letter.await();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
});
public static void main(String[] args) {
numberThread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
letterThread.start();
}
}
网友评论