java多线程实现有序输出ABC

要实现有序输出ABC,可以通过以下几种方式实现:

方式一:使用synchronized关键词

Java中,synchronized关键字可以锁住对象,只允许一个线程访问同一时间内执行的代码块。我们可以使用该关键字来实现对三个线程输出ABC顺序的控制。

public class ABCPrinter implements Runnable {
    private char ch;
    private Object prev;
    private Object self;

    public ABCPrinter(char ch, Object prev, Object self) {
        this.ch = ch;
        this.prev = prev;
        this.self = self;
    }

    public void run() {
        synchronized (prev) {
            while (true) {
                synchronized (self) {
                    System.out.print(ch);
                    self.notify();
                }
                try {
                    prev.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Object a = new Object();
        Object b = new Object();
        Object c = new Object();
        ABCPrinter pa = new ABCPrinter('A', c, a);
        ABCPrinter pb = new ABCPrinter('B', a, b);
        ABCPrinter pc = new ABCPrinter('C', b, c);

        new Thread(pa).start();
        Thread.sleep(10);//保证初始ABC的启动顺序
        new Thread(pb).start();
        Thread.sleep(10);//保证初始ABC的启动顺序
        new Thread(pc).start();
        Thread.sleep(10);//保证初始ABC的启动顺序
    }
}
  • 首先,我们定义了一个类 ABCPrinter,实现了 Runnable 接口,线程对象可以通过该接口创建。
  • 这个类包含了两个 Object 对象,prev 和 self。prev 存储前一个线程的锁对象,self 存储当前线程的锁对象。
  • 在 run() 方法中,我们使用 synchronized(prev) 进入同步锁,如果当前线程不符合执行条件,就让它 wait(),否则就在 synchronized(self) 代码块中输出字符,并通过 self.notify() 唤醒其他等待线程。
  • 此外,我们还在 main 方法中分别启动了三个线程。在每个线程启动前都让程序 sleep 一段时间,保证启动顺序为 ABC。

方式二:使用Lock与Condition

在Java中,Lock与Condition可以实现与synchronized关键词类似的线程同步功能。我们可以使用Lock与Condition来实现多线程的有序输出ABC。

public class ABCPrinter {
    private Lock lock = new ReentrantLock();
    private Condition conditionA = lock.newCondition();
    private Condition conditionB = lock.newCondition();
    private Condition conditionC = lock.newCondition();

    private int currentThread = 0;

    public void printA() throws InterruptedException {
        lock.lock();
        try {
            while (currentThread != 0) {
                conditionA.await();
            }
            System.out.print("A");
            currentThread = 1;
            conditionB.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public void printB() throws InterruptedException {
        lock.lock();
        try {
            while (currentThread != 1) {
                conditionB.await();
            }
            System.out.print("B");
            currentThread = 2;
            conditionC.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public void printC() throws InterruptedException {
        lock.lock();
        try {
            while (currentThread != 2) {
                conditionC.await();
            }
            System.out.print("C");
            currentThread = 0;
            conditionA.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        final ABCPrinter printer = new ABCPrinter();

        new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    printer.printA();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    printer.printB();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    printer.printC();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}
  • 首先,我们定义了一个类 ABCPrinter,该类包含了Lock与Condition对象,用于实现线程同步。
  • ABCPrinter 类还包含了一个 currentThread 状态变量,表示上一个输出的字符。
  • 在 printA、printB、printC 方法中,我们获取锁,如果当前线程不符合执行条件,就调用 await() 方法,让线程进入休眠状态。否则输出字符,并修改 currentThread 状态变量,最后调用 signalAll() 方法,唤醒其他等待线程。

以上就是两种实现多线程有序输出ABC的解决方案。可以根据实际需要来选择适合自己的方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java多线程实现有序输出ABC - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • spring security 自定义Provider 如何实现多种认证

    实现多种认证方式,需要自定义Spring Security的AuthenticationProvider接口实现类,然后在Spring Security配置中引用该实现类。 以下是自定义Provider实现多种认证的步骤: 1.定义一个Authentication实现类该类需要继承AbstractAuthenticationToken类,并重写构造方法和ge…

    Java 2023年6月3日
    00
  • 采集教程及采集分页设置问题

    下面是详细的采集教程及采集分页设置问题的完整攻略。 采集教程 什么是采集 采集是指从一个或多个网站上自动爬取(提取)数据的技术,是一种自动化的数据采集方法。 如何进行采集 进行采集需要用到一些工具,常用的工具有Python爬虫框架Scrapy、PHP采集工具PHP Simple HTML DOM Parser等。 其中,Scrapy是一款强大的Python爬…

    Java 2023年6月16日
    00
  • Spring JdbcTemplate实现添加与查询方法详解

    下面我将详细讲解“Spring JdbcTemplate实现添加与查询方法详解”的完整攻略。 1.介绍 Spring JdbcTemplate是Spring框架中提供的一种使用JDBC进行数据库操作的工具类,它可以简化JDBC的操作,使代码更加简洁易读。Spring JdbcTemplate支持连接池技术,可以很好地处理并发请求。本攻略将详细介绍Spring…

    Java 2023年6月2日
    00
  • SpringBoot整合Redis实现序列化存储Java对象的操作方法

    下面我来详细讲解“SpringBoot整合Redis实现序列化存储Java对象的操作方法”的完整攻略。 一、准备工作 在使用SpringBoot整合Redis以实现Java对象的存储前,我们需要先进行一些准备工作。 在pom.xml中引入Redis相关的依赖,可以使用Jedis或Lettuce两个库。这里我以Lettuce为例: <dependency…

    Java 2023年6月3日
    00
  • Java中的NullPointerException是什么?

    NullPointerException是Java中一个非常普遍的异常,它通常发生在代码中出现了未初始化的变量或者引用被设置为null时。当程序尝试访问一个空对象时就会抛出这个异常。在本文中,我们将详细讲解NullPointerException是什么,为什么会出现,以及如何避免它。 什么是NullPointerException? NullPointerE…

    Java 2023年4月27日
    00
  • Java中后台线程实例解析

    Java中后台线程实例解析 在Java中,线程可以分为前台线程和后台线程。前台线程是指主线程,后台线程是指与主线程并行执行但不会阻止主线程正常结束的线程。本文将详细讲解Java中后台线程的使用方法和示例说明。 后台线程的创建与启动 后台线程可以通过继承Thread类并覆盖run()方法来创建和启动。具体过程如下: public class Backgroun…

    Java 2023年5月18日
    00
  • Mac系统中Apache Tomcat安装配置

    下面是 “Mac系统中Apache Tomcat安装配置” 的完整攻略: 准备工作 在开始安装和配置Apache Tomcat之前,需要确保你的Mac系统上已经安装了Java环境。同时,你需要知道以下几个信息: Apache Tomcat的版本号(例如8.5.65) Apache Tomcat的安装路径(例如/usr/local/tomcat) 安装Apac…

    Java 2023年5月19日
    00
  • Java实现二叉树的基本操作详解

    Java实现二叉树的基本操作详解 二叉树是一种非常常见的树形结构,由于它的具有良好的数据存储和查询性能,在实际开发中也经常使用到。本文将介绍如何使用Java语言实现二叉树的基本操作,包括构建二叉树、插入节点、删除节点、查找节点等功能。 二叉树节点的定义 首先,我们需要定义一个二叉树节点类,它包含三个属性,分别是节点值、左子节点和右子节点,定义如下: clas…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部