面试题多线程轮流打印ABC初试

最近一直在家看传智播客java视频,这几天正好学习到了多线程,在上网看资料的时候发现了一道多线程经典面试题,为了检验自己的水平,就做了下,并写了这篇博客记录。

题目要求:

    建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次   C,要求线程同时运行,交替打印10次ABC。

具体代码:

public class PrintABC
{
    public static void main(String[] args)
    {
        ABC abc = new ABC();
        PrintA pa = new PrintA(abc);
        PrintB pb = new PrintB(abc);
        PrintC pc = new PrintC(abc);


        pa.start();
        pb.start();
        pc.start();
    }
}

class ABC
{
    private boolean flagA = false;
    private boolean flagB = false;
    private boolean flagC = true;

    public int countA = 0;
    public int countB = 0;
    public int countC = 0;
    public synchronized void printA()
    {
        System.out.print("printA被唤醒。。");
        if(this.flagC == true)
        {
            System.out.print("A..." );
            this.flagA = true;
            this.flagC = false;
            System.out.print(++countA+"   ");
        }
    }
    public synchronized void printB()
    {
        System.out.print("printB被唤醒。。");
        if(this.flagA == true )
        {
            System.out.print("B...");
            this.flagB = true;
            this.flagA = false;
            System.out.print(++countB +"   ");
        }
    }
    public synchronized void printC()
    {
        System.out.print("printC被唤醒。。");
        if(this.flagB == true)
        {
            System.out.print("C...");
            this.flagC = true;
            this.flagB = false;
            System.out.println(++countC );
        }
    }
}
class PrintA extends Thread
{
    ABC abc = null;
    PrintA(ABC abc)
    {
        this.abc = abc;
    }
    public void run()
    {
        while(true)
        {
            synchronized(abc)
            {
                abc.printA();
                abc.notify();
                if(abc.countA >= 10)
                    return;
                try
                {
                    abc.wait();
                }
                catch (InterruptedException ie)
                {
                    System.out.println(ie.getMessage());
                }

            }

        }
    //  System.out.println("活动的线程数:" +Thread.activeCount()+"...PrintA线程的状态是:" + this.getState());
    }
}
class PrintB  extends Thread
{
    ABC abc = null;
    PrintB(ABC abc)
    {
        this.abc = abc;
    }
    public void run()
    {
        while(true)
        {
            synchronized(abc)
            {

                abc.printB();
                abc.notify();
                if(abc.countB >= 10)
                    return;
                try
                {
                    abc.wait();
                }
                catch (InterruptedException ie)
                {
                    System.out.println(ie.getMessage());
                }
            }
        }               
    //  System.out.println("活动的线程数:" + Thread.activeCount()+"...PrintB线程的状态是:" + this.getState());
    }

}
class PrintC  extends Thread
{
    ABC abc = null;
    PrintC(ABC abc)
    {
        this.abc = abc;
    }
    public void run()
    {
        while(true)
        {
            synchronized(abc)
            {

                abc.printC();
                abc.notify();
                if(abc.countC >= 10)
                    return ; 
                try
                {
                    abc.wait();
                }
                catch (InterruptedException ie)
                {
                    System.out.println(ie.getMessage());
                }   
            }
        }
    //  System.out.println("活动的线程数:" +Thread.activeCount()+"...PrintC线程的状态是:" + this.getState());
    }
}

输出结果:

面试题多线程轮流打印ABC初试_第1张图片

解题思路:

说下我的思路,这个程序当中建立了五个类,其中类ABC中有三个boolean类型的成员变量flagA、flagB、flagC,用来表示三个字母是否被打印,三个int的变量记录字母的打印状态,然后有三个成员函数用于判断字母的打印状态,并在符合条件时打印字母,并重置字母的打印状态。
然后类PrintA、PrintB、PrintC的思路相同,都是继承Thread类并重写run()方法,为了方便调用类ABC的方法,三个类中都有一个ABC类型的成员变量,并在构造函数中被初始化。然后在run()方法中,都是在while死循环中进行synchronized同步,同步用的锁也都是ABC类型的对象abc,然后在同步代码块中先调用类ABC的print方法,然后notify()方法唤醒同一个锁中的其他线程,然后判断输出了几次字母,如果已经够10次了,就return来结束线程,否则,用wait()方法来冻结线程,等待被再次唤醒。
在主类中,创建了ABC类型的对象,然后创建并开启了三个线程。

结语:

多线程的题目都比较复杂,而且notify()方法唤醒线程时具有不确定性,所以,在调试的时候应该多用输出语句来判断线程的状态。

你可能感兴趣的:(面试题多线程轮流打印ABC初试)