斐讯面试记录—三线程交替打印ABC

简介: 斐讯面试记录—三线程交替打印ABC
package cn.shenzhen.feixun;
public class PrintABC extends Thread{
    private String name;
    private Object prev;
    private Object self;
    public PrintABC(String name,Object prev,Object self){
        this.name=name;
        this.prev=prev;
        this.self=self;
    }
    /**
     * ,为了控制执行的顺序,必须要先持有prev锁,
     * 也就是前一个线程要释放自身对象锁,再去申请自身对象锁,两者兼备时打印字母,
     * 之后首先调用self.notify()释放自身对象锁,唤醒下一个等待线程,
     * 再调用prev.wait()释放prev对象锁,终止当前线程,等待循环结束后再次被唤醒。
     * 程序运行的主要过程就是A线程最先运行,持有C,A对象锁,后释放A,C锁,唤醒B。
     * 线程B等待A锁,再申请B锁,后打印B,再释放B,A锁,唤醒C,线程C等待B锁,再申请C锁,
     * 后打印C,再释放C,B锁,唤醒A……
     */
    public void run(){
        int count=0;
        while(count<10){
            // 先获取 prev锁 如此问题中先将对象C锁住
            synchronized (prev) {
                //然后获取自身的锁如此问题中将对象A锁住
                synchronized (self) {
                    System.out.print(name+"");
                    count++;
                    self.notify();//此问题中一共有三个对象ABC此时将self唤醒,是其他线程来竞争self
                }
                try {
                    prev.wait();
                    /**
                     * 注意的是notify()调用后,并不是马上就释放对象锁,
                     * 而是在相应的synchronized(){}语句块执行结束,自动释放锁,
                     * JVM会在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();
        PrintABC printA=new PrintABC("A", c, a);//第一个线程先将AC对象锁住,A执行完了之后释放锁
        PrintABC printB=new PrintABC("B", a, b);
        PrintABC printC=new PrintABC("C", b, c);
        /**
         * 为了避免JVM启动ThreadA、ThreadB、ThreadC三个线程顺序的不确定性。
         * 需要让A,B,C三个线程以确定的顺序启动,中间加一段sleep确保前一个线程已启动。
         */
        printA.start();
        /**
         * sleep()方法导致了当前线程暂停执行指定的时间,
         * 让出cpu该其他线程,但是他的监控状态依然保持者,
         * 当指定的时间到了又会自动恢复运行状态。
         */
        printA.sleep(10);
        printB.start();
        printB.sleep(10);
        printC.start();
        printC.sleep(10);
    }
}
目录
相关文章
|
9天前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
2月前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
2月前
|
消息中间件 前端开发 NoSQL
面试官:线程池遇到未处理的异常会崩溃吗?
面试官:线程池遇到未处理的异常会崩溃吗?
77 3
面试官:线程池遇到未处理的异常会崩溃吗?
|
2月前
|
消息中间件 存储 前端开发
面试官:说说停止线程池的执行流程?
面试官:说说停止线程池的执行流程?
52 2
面试官:说说停止线程池的执行流程?
|
2月前
|
消息中间件 前端开发 NoSQL
面试官:如何实现线程池任务编排?
面试官:如何实现线程池任务编排?
35 1
面试官:如何实现线程池任务编排?
|
3月前
|
Java
【多线程面试题二十五】、说说你对AQS的理解
这篇文章阐述了对Java中的AbstractQueuedSynchronizer(AQS)的理解,AQS是一个用于构建锁和其他同步组件的框架,它通过维护同步状态和FIFO等待队列,以及线程的阻塞与唤醒机制,来实现同步器的高效管理,并且可以通过实现特定的方法来自定义同步组件的行为。
【多线程面试题二十五】、说说你对AQS的理解
|
3月前
|
消息中间件 缓存 算法
Java多线程面试题总结(上)
进程和线程是操作系统管理程序执行的基本单位,二者有明显区别: 1. **定义与基本单位**:进程是资源分配的基本单位,拥有独立的内存空间;线程是调度和执行的基本单位,共享所属进程的资源。 2. **独立性与资源共享**:进程间相互独立,通信需显式机制;线程共享进程资源,通信更直接快捷。 3. **管理与调度**:进程管理复杂,线程管理更灵活。 4. **并发与并行**:进程并发执行,提高资源利用率;线程不仅并发还能并行执行,提升执行效率。 5. **健壮性**:进程更健壮,一个进程崩溃不影响其他进程;线程崩溃可能导致整个进程崩溃。
51 2
|
3月前
|
存储 缓存 安全
Java多线程面试题总结(中)
Java内存模型(JMM)定义了程序中所有变量的访问规则与范围,确保多线程环境下的数据一致性。JMM包含主内存与工作内存的概念,通过8种操作管理两者间的交互,确保原子性、可见性和有序性。`synchronized`和`volatile`关键字提供同步机制,前者确保互斥访问,后者保证变量更新的可见性。多线程操作涉及不同状态,如新建(NEW)、可运行(RUNNABLE)等,并可通过中断、等待和通知等机制协调线程活动。`volatile`虽不确保线程安全,但能确保变量更新对所有线程可见。
22 0
|
3月前
|
Java 程序员 容器
【多线程面试题二十四】、 说说你对JUC的了解
这篇文章介绍了Java并发包java.util.concurrent(简称JUC),它是JSR 166规范的实现,提供了并发编程所需的基础组件,包括原子更新类、锁与条件变量、线程池、阻塞队列、并发容器和同步器等多种工具。
|
3月前
|
缓存 Java
【多线程面试题二十三】、 说说你对读写锁的了解volatile关键字有什么用?
这篇文章讨论了Java中的`volatile`关键字,解释了它如何保证变量的可见性和禁止指令重排,以及它不能保证复合操作的原子性。
下一篇
无影云桌面