1.多线程轮流打印数字
最简单的代码题,使用两种加锁方式,sychronized和ReentranLock
sychronized
public class Main {
private static final Object lock = new Object();
private static int num = 100;
private static int cnt = 0;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
synchronized (lock) {
if (num <= 0) {
break;
}
if (num % 2 == 0) {
num--;
cnt++;
System.out.println(Thread.currentThread().getName() + ":打印" + cnt);
lock.notify();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
synchronized (lock) {
if (num <= 0) {
break;
}
if (num % 2 == 1) {
num--;
cnt++;
System.out.println(Thread.currentThread().getName() + ":打印" + cnt);
lock.notify();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
});
t1.start();
t2.start();
}
}
ReentranLock
public class Main {
private static final ReentrantLock lock = new ReentrantLock();
private static final Condition condition = lock.newCondition();
private static int num = 100;
private static int cnt = 0;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
try {
lock.lock();
if (num <= 0) {
break;
}
if (num % 2 == 0) {
cnt++;
num--;
System.out.println(Thread.currentThread().getName() + ":打印" + cnt);
condition.signal();
} else {
condition.await();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
try {
lock.lock();
if (num <= 0) {
break;
}
if (num % 2 == 1) {
cnt++;
num--;
System.out.println(Thread.currentThread().getName() + ":打印" + cnt);
condition.signal();
} else {
condition.await();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
});
t1.start();
t2.start();
}
}
多线程竞争数字并统计结果
已经使用过sychronized和ReentranLock,下面使用原子类来完成
public class Main {
private static final AtomicInteger num = new AtomicInteger(100);
private static FutureTask<Integer> getTask() {
return new FutureTask<>(() -> {
int cnt = 0;
while (num.get() > 0) {
num.getAndDecrement();
cnt++;
}
return cnt;
});
}
private static class ThreadMsg {
@Override
public String toString() {
return "ThreadMsg{" +
"threadName='" + threadName + '\'' +
", score=" + score +
'}';
}
public ThreadMsg(String threadName, Integer score) {
this.threadName = threadName;
this.score = score;
}
private String threadName;
private Integer score;
public Integer getScore() {
return score;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> task1 = getTask();
FutureTask<Integer> task2 = getTask();
FutureTask<Integer> task3 = getTask();
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
Thread t3 = new Thread(task3);
t1.start();
t2.start();
t3.start();
ArrayList<ThreadMsg> list = new ArrayList<ThreadMsg>() {{
add(new ThreadMsg(t1.getName(), task1.get()));
add(new ThreadMsg(t2.getName(), task2.get()));
add(new ThreadMsg(t3.getName(), task3.get()));
}};
list.sort(Comparator.comparingInt(ThreadMsg::getScore));
System.out.println(list);
}
}
由于非公平竞争,可能会出现一个线程抢完所有所有数字,可以人为引入延迟
Thread.sleep(1)
也可以加大原子类初始数字
以下为使用ReentranLock,其他不变
private static int num = 100;
private static final ReentrantLock lock = new ReentrantLock();
private static FutureTask<Integer> getTask() {
return new FutureTask<>(() -> {
int cnt = 0;
while (true) {
lock.lock();
try {
if (num <= 0) {
break;
}
num--;
cnt++;
} finally {
lock.unlock();
}
}
return cnt;
});
}
生产者消费者模型
在此处缓冲区使用线程安全类BlockingQueue来实现,其安全性由原子ReentranLock锁实现,其put和take都是阻塞的,所以无需加锁,实现更加简单
以下为具体实现
public class Main {
private static final BlockingQueue<Integer> buffer = new LinkedBlockingQueue<>(10);
private static final Random random = new Random();
static class Producer implements Runnable {
@Override
public void run() {
try {
int value = random.nextInt(1000);
buffer.put(value);
System.out.println(Thread.currentThread().getName() + ":生产了" + value);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
static class Consumer implements Runnable {
@Override
public void run() {
try {
Integer i = buffer.take();
System.out.println(Thread.currentThread().getName() + ":消费了" + i);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
new Thread(new Producer(), "生产者" + i).start();
}
for (int i = 0; i < 10; i++) {
new Thread(new Consumer(), "消费者者" + i).start();
}
}
}
标签:面试题,Thread,lock,涵盖,private,num,static,new,多线程
From: https://blog.csdn.net/weixin_46684043/article/details/142414026