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

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

  • 相关阅读:
    eclipse两种注释的快捷键
    为什么我的安卓虚拟机没有虚拟键盘
    windows server2012部署apache项目访问后台管理系统时tomcat就停了是怎么回事
    什么时候你可以考虑离职?遇到这6种情况
    安装wampserver后,在www文件夹下面写php文件,而在网页里输入localhost而无法打开php文件时解决办法汇总
    访问localhost文件下的testmysql.php文件报Not Found
    访问localhost的phpmyadmin出现访问被拒绝
    wamp如何设置数据库的密码
    WAMP不能启动, 一直处于红色图标或者橙色图标的解决办法
    [AngularJS] Decorator a directive
  • 原文地址:https://www.cnblogs.com/dwwzone/p/13291464.html
Copyright © 2011-2022 走看看