zoukankan      html  css  js  c++  java
  • 实现两条线程交替打印奇偶数的两种简单方法

    实现两条线程交替打印奇偶数的两种简单方法

    使用Synchronized

    public class Main {
    
        private int count = 0;
    
        public static void main(String[] args) throws InterruptedException {
            Main main = new Main();
            new Thread(()->{
                for (int i = 0; i < 50; i++) {
                    try {
                        main.printEven();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"A").start();
    
            new Thread(()->{
                for (int i = 0; i < 50; i++) {
                    try {
                        main.printOdd();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"B").start();
        }
    	
       	//打印奇数方法
        public  synchronized void printOdd() throws InterruptedException {
            while (this.count % 2 == 0) {//如果是偶数,则阻塞,释放锁
                this.wait();
            }
            System.out.println(Thread.currentThread().getName() + this.count++);
            this.notifyAll();//唤醒阻塞线程
        }
    	
        //打印偶数方法
        public  synchronized void printEven() throws InterruptedException {
            while (this.count % 2 != 0) {//如果是奇数,则阻塞,释放锁
                this.wait();
            }
            System.out.println(Thread.currentThread().getName() + this.count++);
            this.notifyAll();//唤醒阻塞线程
        }
    }
    

    此方法不容易扩展到多条线程,越多的线程在唤醒时会经历越多的竞争,加大CPU资源浪费,同时也增加耗时

    使用ReetrantLock+Condition实现精准唤醒

    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Turning {
    
        public static void main(String[] args) throws InterruptedException {
            Turning turning = new Turning();
            new Thread(()->{
                for (int i = 0; i < 50; i++) {
                    turning.printO();
                }
            },"A").start();
            Thread.sleep(1000);
            new Thread(()->{
                for (int i = 0; i < 50; i++) {
                    turning.printJ();
                }
            },"B").start();
        }
    
        private ReentrantLock lock = new ReentrantLock();
        private Condition condition1 = lock.newCondition();
        private Condition condition2 = lock.newCondition();
    
        private int number = 0;
    
        public void printJ() {
            lock.lock();
            try {
                while (number % 2 == 0) {
                    condition1.await(); //如果是偶数,在此处阻塞
                }
                System.out.println(Thread.currentThread().getName()+number++);
                condition2.signal(); //唤醒在2处阻塞的线程
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    
        public void printO() {
            lock.lock();
            try{
                while (number % 2 != 0) { 
                    condition2.await(); //如果是奇数,在此处阻塞
                }
                System.out.println(Thread.currentThread().getName()+number++);
                condition1.signal(); //唤醒在1处阻塞的线程
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }
    

    此方法容易扩展到多条线程交替,且为精准唤醒,减少线程竞争带来的消耗

  • 相关阅读:
    识别浏览器信息,判断是否安卓或者苹果手机
    thinkphp5.0 配置文件加载路径说明
    thinkphp5.0 url跳转
    微信小程序--picker
    JavaScript和php数组的定义
    地点下来框的实现(php)
    微信小程序入门(持续更新)
    Vue 拖拽组件 vuedraggable 和 vue-dragging
    递归
    js 为什么有些在原始数据上进行修改,有些进行浅拷贝或深拷贝呢
  • 原文地址:https://www.cnblogs.com/dwwzone/p/13291464.html
Copyright © 2011-2022 走看看