welcome to my blog
问题: 线程A向一个map中存数据, 然后线程B从map中取数据, 循环这个过程, 最终效果像: 线程A存入1, 线程B取出1, 线程A存入2, 线程B取出2, 线程A存入3, 线程B取出3… 直到线程A存入100, 线程B取出100
问题的要求非常像生产者消费者模式, 但是有个很大的区别, 那就是生产者的生产和消费者的消费没有顺序要求, 但是这道题要求线程A和线程B轮流执行
考察点: 如何让两个线程轮流执行
考察点: 如何让两个线程轮流执行
考察点: 如何让两个线程轮流执行
下面写了五个例子
前三个例子使用了阻塞+唤醒的思路, 涉及用户态和内核态的切换, 效率偏低, 但是CPU压力小
后两个例子使用了vaolatile+CAS, 不能操作时通过自旋进行等待, 更高效, 但是CPU压力大
方法一: 使用synchronized修饰函数
import java.util.HashMap;
public class Study {
public static void main(String[] args) {
MyTest test = new MyTest();
//充当线程A的角色
new Thread() {
@Override
public void run() {
test.put();
}
}.start();
//充当线程A的角色
new Thread() {
@Override
public void run() {
test.get();
}
}.start();
}
}
class MyTest {
HashMap<Integer, Integer> map = new HashMap<>();
int i = 1;
synchronized void put() {
for (int k = 0; k < 100; k++) {
map.put(i, i);
System.out.println(Thread.currentThread().getName() + " " + i);
i++;
this.notify(); //等待队列中只有一个线程, 所以不用使用notifyAll()
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "执行完毕");
}
synchronized void get() {
for (int k = 0; k < 100; k++) {
int cur = map.get(i - 1);
System.out.println(Thread.currentThread().getName() + " " + cur);
this.notify();
try {
//最多等待1s, 等待1s后没被唤醒则自己醒过来
//因为最后一次循环时, 当前方法让出CPU后, 再也不会被唤醒了
this.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "执行完毕");
}
}
/*
打印结果
...
Thread-0 97
Thread-1 97
Thread-0 98
Thread-1 98
Thread-0 99
Thread-1 99
Thread-0 100
Thread-1 100
Thread-0执行完毕
Thread-1执行完毕
*/
方法二: 使用synchronized代码块
import java.util.HashMap;
public class Study {
public static void main(String[] args) {
MyTest test = new MyTest();
//充当线程A的角色
new Thread() {
@Override
public void run() {
test.put();
}