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();
            }
        }
    }
    

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

  • 相关阅读:
    12-单表查询
    11-数据的增删改
    10-外键的变种 三种关系
    09-完整性约束
    08-数据类型(2)
    07-数据类型
    06-表的操作
    05-库的操作
    Spring:(六) 代理模式
    Spring:(五) 注解
  • 原文地址:https://www.cnblogs.com/dwwzone/p/13291464.html
Copyright © 2011-2022 走看看