`

顺序打印ABC------java多线程的一道经典面试题

阅读更多

 

public class PrintABC {

    public static Boolean isThreadA = true;
    public static Boolean isThreadB = false;
    public static Boolean isThreadC = false;

    public static void main(String[] args) {
        final PrintABC abc = new PrintABC();
        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    synchronized (abc) {
                        while(!isThreadA) {
                            try {
                                abc.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                            System.out.print("A");
                            isThreadA = false;
                            isThreadB = true;
                            isThreadC = false;
                            abc.notifyAll();
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    synchronized (abc) {
                        while(!isThreadB) {
                            try {
                                abc.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                            System.out.print("B");
                            isThreadA = false;
                            isThreadB = false;
                            isThreadC = true;
                            abc.notifyAll();
                    }
                }
            }
        }).start();
       
        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    synchronized (abc) {
                        while(!isThreadC) {
                            try {
                                abc.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                            System.out.print("C");
                            isThreadA = true;
                            isThreadB = false;
                            isThreadC = false;
                            abc.notifyAll();
                    }
                }
            }
        }).start();
    }
}

 

输出结果如下 :ABCABCABCABCABC

思路:解题思路大概是这样的,开启三个线程,每个线程一次打印一个字母,并且按照一定 的顺序打印,当打印A的时候,其他线程处于阻塞状态,打印完A以后,将线程解锁,让打印B的那个线程开启,其他线程处于阻塞状态,同理打印C的时候,阻塞 其他线程,这三个线程顺序循环,就达到顺序多次打印ABC的目的了。

这道题看似思路简单,其实主要需要用到wait()方法和notify()方法,还有关键字synchronized,只有充分理解了这些,才能解出这道题。下面我有必要讲解一下这两个方法,还有关键字synchronized。

 

在 JAVA中,是没有类似于PV操作、进程互斥等相关的方法的。JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的 synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁 后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。明白这个原理,就能理解为什么synchronized(this)与 synchronized(static XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类的一个对象,所以其内存锁是针对相同对象的互斥操作,而 static成员属于类专有,其内存空间为该类所有成员共有,这就导致synchronized()对static成员加锁,相当于对类加锁,也就是在该 类的所有成员间实现互斥,在同一时间只有一个线程可访问该类的实例。如果只是简单的想要实现在JAVA中的线程互斥,明白这些基本就已经够了。但如果需要 在线程间相互唤醒的话就需要借助Object.wait(), Object.nofity()了。

    Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取 了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功 能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象 锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的 synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执 行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要 的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。理解了这些解决这道面试题应该就不成问题了

分享到:
评论

相关推荐

    java多线程每个线程挨着打印ABC的4种实现方式

    java多线程每个线程挨着打印ABC的4种实现方式,有4个线程t1、t2、t3、t4,t1打印A后t2打印A再t3打印A再t4打印A,然后从新回到t1打印B再t2打印B...t4打印B... 4个线程轮流打印abc... 一个线程可以理解为一个人,打印...

    java经典面试题

    ### Java经典面试题知识点 #### Java数据结构容器 - **核心知识点**:Java集合框架,包括List、Set、Map等接口及其实现类。List接口代表有序的集合,例如ArrayList和LinkedList;Set接口代表不允许重复元素的集合,...

    abc ----VB家庭收支管理

    abc ----VB家庭收支管理abc ----VB家庭收支管理abc ----VB家庭收支管理abc ----VB家庭收支管理abc ----VB家庭收支管理abc ----VB家庭收支管理abc ----VB家庭收支管理abc ----VB家庭收支管理abc ----VB家庭收支管理...

    java多线程实现轮流打印ABC

    使用多线程和阻塞队列实现了ABC字母按顺序轮流打印

    MATLAB中的abc-dq相坐标变换

    MATLAB中的abc-dq相坐标变换 MATLAB中的abc-dq相坐标变换是指在MATLAB软件中实现的坐标变换,从三相坐标系到两相旋转坐标系的变换。这种变换有两个步骤:首先,将三相坐标系变换到两相静止坐标系,然后将两相静止...

    java面试题-经典选择题部分

    - 方法重载(Overloading)指的是在一个类中可以有多个同名的方法,但是这些方法的参数列表必须不同(参数的数量、类型或顺序不同)。 - 选项A改变了方法的访问修饰符,这不影响是否构成重载。 - 选项B改变了返回值...

    基于ABC-BP神经网络的年均含沙量预测研究.pdf

    基于ABC-BP神经网络的年均含沙量预测研究 摘要:本文介绍了基于ABC-BP神经网络的年均含沙量预测模型,该模型结合人工蜂群算法优化了BP神经网络的权值和阈值,从而提高了模型的预测精度。该模型可以为河道治理和防洪...

    Java多线程连续打印abc实现方法详解

    Java多线程连续打印abc实现方法详解 Java多线程连续打印abc实现方法详解是 Java 编程...解决 Java 多线程连续打印abc问题需要使用同步机制来确保三个线程的顺序执行。可以使用两个锁或信号量来实现该问题的解决方案。

    ABC-K-means.rar_ABC_MATLAB 聚类_k means改进算法_k均值聚类_蜂群matlab

    ABC-K-means.rar 是一个包含MATLAB实现的文件包,主要关注的是K-means聚类算法的一种改进版本,即结合了人工蜂群算法(Artificial Bee Colony, ABC)的优化策略。K-means聚类是一种广泛应用的数据分析方法,用于将...

    蜂群SVM(ABC-SVM)遗传算法SVM(GA-SVM)粒子群SVM(PSO-SVM)公共数据集,UCMerced图像数据集 词袋模型

    标题中的“蜂群SVM(ABC-SVM)遗传算法SVM(GA-SVM)粒子群SVM(PSO-SVM)”是指利用生物进化算法优化支持向量机(Support Vector Machine, SVM)的一种方法。SVM是一种强大的监督学习模型,广泛应用于分类和回归...

    基于ABC-BP神经网络预测钢筋锈蚀程度.pdf

    "基于ABC-BP神经网络预测钢筋锈蚀程度.pdf" 通过对基于ABC-BP神经网络预测钢筋锈蚀程度的研究,我们可以了解到ABC-BP神经网络在钢筋锈蚀程度预测中的应用。该网络通过人工蜂群算法和BP神经网络原理相结合,设计出了...

    abc.rar_ABC_java多线程下载

    标题中的"abc.rar_ABC_java多线程下载"表明这是一个关于Java多线程下载技术的压缩文件,其中"abc.rar"可能是文件的主名,而"ABC"可能是一种分类或者项目代号。描述中的"复件 Java多线程下载演示文件wdown.jar"暗示了...

    abc.rar_ABC_java_java面试题

    Java作为一门广泛使用的编程语言,其面试题涵盖了众多的知识领域,包括基础语法、面向对象编程、集合框架、多线程、异常处理、JVM、IO流、网络编程、设计模式等。对于Java开发者来说,理解和掌握这些知识点是提升...

    java 经典面试题

    这些知识点不仅涵盖了基本概念,还涉及了一些进阶技巧,对于准备Java面试的人来说非常有用。 ### 1. Java 基本数据类型和输出 #### 示例题目: ```java int x = 010, y = 10, z = 0x10; System.out.println(x + "...

    ABC-Linux-V.2.4.3-alpha.tar.gz_ABC

    ABC-Linux-V.2.4.3-alpha.tar.gz 是一个针对Linux操作系统的压缩包文件,其版本号为2.4.3,标记为"alpha",意味着这是一个早期测试版,可能包含未解决的问题和功能不完善之处。这个软件主要用于BT(BitTorrent)下载...

    java面试题-解密版

    ### Java面试题解析 #### 1. 数据库连接池的工作机制 数据库连接池是一种用于管理数据库连接的技术。它预先创建多个数据库连接,并将其保存在一个池中。当应用程序需要访问数据库时,可以从池中获取一个已经建立好...

    java面向对象练习题-经典

    Java面向对象练习题经典 Java面向对象练习题是Java编程语言中非常重要的一部分,这些练习题涵盖了Java语言的基础知识,包括Java基本数据类型、运算符、控制结构、方法、类和对象、继承、多态、抽象类和接口等方面。...

    java 经典面试笔试题

    ### Java经典面试笔试题知识点解析 #### 一、判断题知识点解析 1. **创建类对象与回收对象** - **知识点**: 在Java中,创建一个新的类对象使用的关键字是`new`,而不是`free`。`new`操作符用于在内存中为对象分配...

Global site tag (gtag.js) - Google Analytics