Java多线程代码题
预览主题default
代码主题atom
面试的时候被问到一些多线程面试题,没有做出来,写一下记录一下。
双线程轮流打印1-100
使用两个线程,其中一个打印奇数,另外一个打印偶数
java
public class TwoThreadPrintNumber {
private final static Object lock = new Object();
public static int num = 1;
public static void main(String[] args) {
TwoThreadPrintNumber twoThreadPrintNumber = new TwoThreadPrintNumber();
Thread thread1 = new Thread(() -> {
twoThreadPrintNumber.printNumber(true);
},"偶数线程");
Thread thread2 = new Thread(() -> {
twoThreadPrintNumber.printNumber(false);
},"奇数线程");
thread1.start();
thread2.start();
}
// true 打印偶数 否则打印奇数
private void printNumber(boolean type) {
while (num <= 100) {
synchronized (lock) {
while ((type && num % 2 == 1) || (!type && num % 2 == 0)) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (num <= 100) {
System.out.println(Thread.currentThread().getName() + " print " + num);
num++;
lock.notifyAll();
}
}
}
}
}
printNumber中为什么使用while,而不是使用if
为了避免线程的虚假唤醒,当线程进入等待状态后,有可能会在没有被其他线程调用
notify或者notifyAll方法的情况下被唤醒,这种情况就被称为虚假唤醒。如果使用
if语句,假设线程被虚假唤醒了,就会执行if语句后面的打印代码,而不是再次检查条件是否满足,最终导致打印结果不符合预期;而使用while语句,线程被唤醒后会再次检查while条件,从而避免虚假唤醒带来的问题。
同步代码块中为什么还需要再判断一次 if (num <= 100)
为了线程安全,当一个线程被唤醒后,虽然它已经重新获得锁了,但是等待期间可能其他线程已经将
num值增加到超过100的值了,所以打印之前需要重新检查一下。
三个线程顺序打印1-100
java
public class ThreeThreadPrint {
private static int number = 1;
public static final Object lock = new Object();
public static void main(String[] args) {
ThreeThreadPrint threeThreadPrint = new ThreeThreadPrint();
Thread thread1 = new Thread(() -> {
threeThreadPrint.printNumber(0);
}, "3n");
Thread thread2 = new Thread(() -> {
threeThreadPrint.printNumber(1);
}, "3n+1");
Thread thread3 = new Thread(() -> {
threeThreadPrint.printNumber(2);
}, "3n+2");
thread1.start();
thread2.start();
thread3.start();
}
private void printNumber(int type) {
while (number <= 100) {
synchronized (lock) {
while (number % 3 != type) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (number <= 100) {
System.out.println(Thread.currentThread().getName() + " print " + number);
number++;
lock.notifyAll();
}
}
}
}
}
线程A、B、C,分别打印1、2、3,顺序执行10次
java
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class SequentialPrint {
private static final Object lockObj = new Object();
private static int count = 0;
public static int offset =0;
private static final ReentrantLock lock = new ReentrantLock();
private static final Condition conditionA = lock.newCondition();
private static final Condition conditionB = lock.newCondition();
private static final Condition conditionC = lock.newCondition();
public static int type = 1;
public static final int MAX_LOOP = 10;
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
printNumber(1, 1, conditionA, conditionB);
}, "线程A");
Thread threadB = new Thread(() -> {
printNumber(2, 2, conditionB, conditionC);
}, "线程B");
Thread threadC = new Thread(() -> {
printNumber(3, 0, conditionC, conditionA);
}, "线程C");
threadA.start();
threadB.start();
threadC.start();
Thread threadA1 = new Thread(() -> {
printNumber(1);
}, "线程A");
Thread threadB1 = new Thread(() -> {
printNumber(2);
}, "线程B");
Thread threadC1 = new Thread(() -> {
printNumber(3);
}, "线程C");
threadA1.start();
threadB1.start();
threadC1.start();
}
private static void printNumber(int number, int target, Condition curr, Condition nextThread) {
for (int i = 0; i < MAX_LOOP; i++) {
lock.lock();
try {
while (type % 3 != target) {
curr.await();
}
System.out.println(Thread.currentThread().getName() + " print " + number);
type++;
nextThread.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
private static void printNumber(int number) {
for (int i = 0; i < MAX_LOOP; i++) {
synchronized (lockObj) {
while (offset % 3 != number - 1) {
try {
lockObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count < 30) {
System.out.println(Thread.currentThread().getName() + " print " + number);
offset++;
count++;
lockObj.notifyAll();
}
}
}
}
}
100个线程,每个线程累加100次
java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicCount {
public static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 100; i++) {
executor.submit(() -> {
for (int j = 0; j < 100; j++) {
count.incrementAndGet();
}
});
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
System.out.println("count = " + count.get());
}
}
线程交叉打印12A34B56C
java
public class CrossingPrint {
public static final Object lock = new Object();
// true 打印数字
public static boolean flag = true;
private static int cnt = 0;
private static int num = 1;
private static Character letter = 'A';
public static void main(String[] args) {
Thread numberPrintThread = new Thread(() -> {
crossPrint(true);
}, "NumberPrintThread");
Thread letterPrintThread = new Thread(() -> {
crossPrint(false);
}, "LetterPrintThread");
numberPrintThread.start();
letterPrintThread.start();
}
private static void crossPrint(boolean currFlag) {
while (cnt < 78) {
synchronized (lock) {
while (flag != currFlag) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (cnt < 78) {
if (currFlag) {
System.out.println(num++);
System.out.println(num++);
cnt += 2;
} else {
System.out.println(letter++);
cnt++;
}
flag = !flag;
lock.notifyAll();
}
}
}
}
}
模拟购票系统 500张票 有1-4编号的4个购票窗口,模拟购票流程,打印购票结果
java
public class BuyTicket {
private volatile static int ticketTotal = 500;
private static final Object lock = new Object();
public static void main(String[] args) {
for (int i = 1; i <= 4; i++) {
new Thread(BuyTicket::buyTicket, i + "").start();
}
}
private static void buyTicket() {
while (ticketTotal > 0) {
synchronized (lock) {
if (ticketTotal > 0) {
--ticketTotal;
System.out.println(Thread.currentThread().getName() + "购买1张票, 剩余票数为:" + ticketTotal);
}
}
try {
// 休眠增加窗口随机性
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
生产者-消费者模式
synchronized+wait+notify实现
java
public class ProductConsumer {
public static final Object lock = new Object();
public static int currCnt = 0;
private static final int BUFFER_SIZE = 5;
private static Object[] buffer = new Object[BUFFER_SIZE];
private static int inIndex = 0;
private static int outIndex = 0;
public static void main(String[] args) {
Product product = new Product();
Consumer consumer = new Consumer();
product.start();
consumer.start();
}
static class Product extends Thread {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
synchronized (lock) {
while (currCnt >= BUFFER_SIZE) {
System.out.println("队列已满 生产者等待");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
buffer[inIndex] = i;
inIndex = (inIndex + 1) % BUFFER_SIZE;
currCnt++;
System.out.println("生产数据: " + i + " 缓冲区数量: " + currCnt);
lock.notify();
}
}
}
}
static class Consumer extends Thread {
@Override
public void run() {
while (true) {
synchronized (lock) {
while (currCnt <= 0) {
System.out.println("队列已空 消费者等待");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object data = buffer[outIndex];
currCnt--;
System.out.println("消费消息: " + data + " 缓冲区数量: " + currCnt);
outIndex = (outIndex + 1) % BUFFER_SIZE;
lock.notify();
}
}
}
}
}
ReentrantLock + Condition实现
java
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ProductConsumerWithReenLock {
public static final ReentrantLock lock = new ReentrantLock();
public static final Condition notFull = lock.newCondition();
public static final Condition notEmpty = lock.newCondition();
public static int currCnt = 0;
private static final int BUFFER_SIZE = 5;
private static Object[] buffer = new Object[BUFFER_SIZE];
private static int inIndex = 0;
private static int outIndex = 0;
public static void main(String[] args) {
Product product = new Product();
Consumer consumer = new Consumer();
product.start();
consumer.start();
}
static class Product extends Thread {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
lock.lock();
try {
while (currCnt >= BUFFER_SIZE) {
System.out.println("队列已满 生产者等待");
notFull.await();
}
Thread.sleep(100);
buffer[inIndex] = i;
inIndex = (inIndex + 1) % BUFFER_SIZE;
currCnt++;
System.out.println("生产数据: " + i + " 缓冲区数量: " + currCnt);
notEmpty.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
static class Consumer extends Thread {
@Override
public void run() {
while (true) {
lock.lock();
try {
while (currCnt <= 0) {
System.out.println("队列已空 消费者等待");
notEmpty.await();
}
Object data = buffer[outIndex];
currCnt--;
System.out.println("消费消息: " + data + " 缓冲区数量: " + currCnt);
outIndex = (outIndex + 1) % BUFFER_SIZE;
notFull.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
}
Java实现单例模式
懒汉式
java
public class EagerSingleton {
// 饿汉式
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {
// 防止发射创建实例
if (INSTANCE != null) {
throw new IllegalStateException("已初始化");
}
}
public static EagerSingleton getInstance() {
return INSTANCE;
}
}
懒汉式
线程不安全版
java
public class UnsafeLazySingleton {
private static UnsafeLazySingleton instance;
private UnsafeLazySingleton() {}
public static UnsafeLazySingleton getInstance() {
if (instance == null) {
// 多线程可能创建多实例
instance = new UnsafeLazySingleton();
}
return instance;
}
}
线程安全版
java
public class SyncLazySingleton {
private static SyncLazySingleton instance;
private SyncLazySingleton() {}
public static synchronized SyncLazySingleton getInstance() {
if (instance == null) {
instance = new SyncLazySingleton();
}
return instance;
}
}
双重检测锁
java
public class DoubleCheckLockSing {
private static DoubleCheckLockSing instance;
private DoubleCheckLockSing() {}
public static DoubleCheckLockSing getInstance() {
if (instance == null) {
synchronized (DoubleCheckLockSing.class) {
if (instance == null) {
instance = new DoubleCheckLockSing();
}
}
}
return instance;
}
}
静态内部类
java
public class HolderSingleton {
private HolderSingleton() {}
private static class Holder {
static final HolderSingleton INSTANCE = new HolderSingleton();
}
public static HolderSingleton getInstance() {
return Holder.INSTANCE;
}
}
作者:LSL
类型:原创
本文链接:https://lslshiba.top/article/16
此文章版权归LSL所有,如有转载请注明原作者。
