java 两个线程轮流执行 五种方法

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();
            }
        
  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值