看了好多的面经,手撕代码中除了算法题最常出现多线程的问题了,以下几个问题是总结了下出现比较多的,做一下记录,方便多看看
多线程下卖票
synchronized实现
只要有票就可以卖,卖之前第二次检查,保证多线程下不会卖出负数
class SellTacket implements Runnable {
static int count = 100;
static Object lock = new Object();
public static void main(String[] args) {
SellTacket sellTacket = new SellTacket();
for (int i = 0; i < 20; i++) {
new Thread(sellTacket, "卖票员" + i).start();
}
}
@Override
public void run() {
while (count > 0) {
synchronized (lock) {
if (count > 0) {
count--;
System.out.println(Thread.currentThread().getName() + "卖出一张票,库存为:" + count);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
两个线程交替打印0-100奇偶数
两个线程启动之间睡眠1秒,保证偶数线程先启动
当打印完成一次后唤醒另一个线程,如果还有打印任务就wait当前线程等待被唤醒
class MyPrint implements Runnable {
private static int count = 0;
private static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
new Thread(new MyPrint(), "偶数").start();
Thread.sleep(1000);
new Thread(new MyPrint(), "奇数").start();
}
@Override
public void run() {
while (count <= 100) {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + ":" + count++);
lock.notifyAll();
if (count <= 100) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
三个线程交替打印0-100的数
三个线程就不能简单的执行文唤醒直接执行了
使用ReentrantLock+自旋+双重检查
操作,如果线程执行到打印位置不该他打印,就自旋等待合适了再操作
class MyPrint {
private static Lock lock = new ReentrantLock();//定义一个lock锁
private static int count = 0;//确定打印的是什么内容
public static void main(String[] args) {
new ThreadA().start();
new ThreadB().start();
new ThreadC().start();
}
static class ThreadA extends Thread {
@Override
public void run() {
while (count <= 100) {
try {
lock.lock();
while (count % 3 == 0 && count <= 100) {
//自旋
System.out.println(Thread.currentThread().getName() + ":" + count++);
}
} finally {
lock.unlock();
}
}
}
}
static class ThreadB extends Thread {
@Override
public void run() {
while (count <= 100) {
try {
lock.lock();
while (count % 3 == 1 && count <= 100) {
//自旋
System.out.println(Thread.currentThread().getName() + ":" + count++);
}
} finally {
lock.unlock()