三个线程循环打印ABC10次的几种解决方法

题目:有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕打印10次ABC

整体思路:该问题为三个线程的同步唤醒机制即ThreadA->ThreadB->ThreadC->ThreadA循环执行三个线程。

public class MyThreadPrinter2 implements Runnable {

    private String name;
    private Object prev;
    private Object self;
    private Thread thread;

    public MyThreadPrinter2(String name,Object prev,Object self) {
        this.name=name;
        this.prev=prev;
        this.self=self;
        thread=new Thread(this,name);
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        int count=10;
        while (count>0) {
            synchronized (prev) {
                synchronized (self) {
                    System.out.print(name);
                    count--;

                    self.notify();
                }
                try {
                    prev.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        Object aObject=new Object();
        Object bObject=new Object();
        Object cObject=new Object();

        MyThreadPrinter2 pa=new MyThreadPrinter2("A", cObject, aObject);
        MyThreadPrinter2 pb=new MyThreadPrinter2("B", aObject, bObject);
        MyThreadPrinter2 pc=new MyThreadPrinter2("c", bObject, cObject);

        pa.thread.start();
//         try {
//            Thread.sleep(1);
//        } catch (InterruptedException e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        }
        pb.thread.start();
//         try {
//                Thread.sleep(10);
//            } catch (InterruptedException e) {
//                // TODO Auto-generated catch block
//                e.printStackTrace();
//            }
        pc.thread.start();
//         try {
//                Thread.sleep(10);
//            } catch (InterruptedException e) {
//                // TODO Auto-generated catch block
//                e.printStackTrace();
//            }
    }

}

运行后的打印结果为ACBACBACBACBACBACBACBACBACBACB。最后通过在start()中做延迟可以解决顺序不正确的问题。此方法用到两个锁,有些浪费资源。还有个问题就是打印后,程序还在运行。

针对以上问题,可以采用sleep方法

public class SleepExample extends Thread{

    private static int currentCount=0;

    public SleepExample(String name) {
        this.setName(name);
    }

    @Override
    public void run() {
        while (currentCount<30) {
            switch (currentCount%3) {
            case 0:
                if ("A".equals(getName())) {
                    printAndIncrease();
                }
                break;

            case 1:
                if ("B".equals(getName())) {
                    printAndIncrease();
                }
                break;

            case 2:
                if ("C".equals(getName())) {
                    printAndIncrease();
                }
                break;

            default:
                break;
            }
        }
    }

    private void printAndIncrease() {
        // TODO Auto-generated method stub
        print();
        increase();
    }

    private void increase() {
        currentCount++;
    }

    private void print() {
        System.out.print(getName());
        if ("C".equals(getName())) {
            System.out.println();
        }
    }

    public static void main(String[] args) {
        new SleepExample("A").start();
        new SleepExample("B").start();
        new SleepExample("C").start();
    }

}

通过currentCount%3的余数控制线程打印A、B、C的顺序。也就是通过currentCount%3的余数来控制Thread.sleep()状态。
使用synchronized,wait和notify

public class PrintRunable implements Runnable{

    private LetterPrinter letterPrinter=null;

    private char letter=‘ ‘;

    public PrintRunable(LetterPrinter letterPrinter,char letter) {
        super();
        this.letterPrinter=letterPrinter;
        this.letter=letter;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 10; i++) {
            synchronized (letterPrinter) {
                while (letter!=letterPrinter.getLetter()) {
                    try {
                        letterPrinter.wait();//告知被调用的线程放弃管程进入休眠直到其他线程进入相同的管程并且调用notify()/notifyAll()
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

                letterPrinter.Print();
                letterPrinter.nextLetter();
                letterPrinter.notifyAll();//恢复相同对象中第一个调用wait()的线程

            }
        }
    }

}

字母打印顺序:

public class LetterPrinter {
    private char letter=‘A‘;

    void Print(){
        System.out.print(letter);
        if (‘C‘==letter) {
            System.out.println();
        }
    }

    void nextLetter() {
        switch (letter) {
        case ‘A‘:
            letter=‘B‘;
            break;

        case ‘B‘:
            letter=‘C‘;
            break;

        case ‘C‘:
            letter=‘A‘;
            break;

        default:
            break;
        }
    }

    /**
     * @return the letter
     */
    public char getLetter() {
        return letter;
    }

}
public class PrintThreadExample {    

    public static void main(String[] args) {

        LetterPrinter letterPrinter=new LetterPrinter();

        ExecutorService service=Executors.newFixedThreadPool(3);

        service.execute(new PrintRunable(letterPrinter, ‘A‘));//开启A线程
        service.execute(new PrintRunable(letterPrinter, ‘B‘));//开启B线程
        service.execute(new PrintRunable(letterPrinter, ‘C‘));//开启C线程
        service.shutdown();//结束程序
    }

}

使用Lock方法

public class ABC {

    private static int state=0;

    public static void main(String[] args) {
        final Lock lock=new ReentrantLock();

        Thread A=new Thread(new Runnable() {
            public void run() {
                while (state<=30) {
                    lock.lock();//get lock
                    if (state%3==0) {
                        System.out.print("A");
                        state++;
                    }
                    lock.unlock();//release lock
                }
            }
        });

        Thread B=new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (state<=30) {
                    lock.lock();//get lock
                    if (state%3==1) {
                        System.out.print("B");
                        state++;
                    }
                    lock.unlock();//release lock
                }
            }
        });

        Thread C=new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (state<=30) {
                    lock.lock();//get lock
                    if (state%3==2) {
                        System.out.print("C");
                        state++;
                    }
                    lock.unlock();//release lock
                }
            }
        });

        A.start();
        B.start();
        C.start();
    }

}
时间: 2024-10-04 21:11:45

三个线程循环打印ABC10次的几种解决方法的相关文章

.NET中TextBox控件设置ReadOnly=true后台取不到值三种解决方法

.NET中TextBox控件设置ReadOnly=true后台取不到值三种解决方法 当TextBox设置了ReadOnly=true后要是在前台为控件添加了值,后台是取不到的,值为空,多么郁闷的一个问题经过尝试,发现可以通过如下的方式解决这个问题.感兴趣的朋友可以了解下 当TextBox设置了ReadOnly="true" 后,要是在前台为控件添加了值,后台是取不到的,值为“空” 原理没想通,说不清楚微软是出于什么考虑的,不过有时是要我们能通过前台脚本来填充值,并不希望用户修改其控件内

WordPress程序打开速度慢的三种解决方法

WordPress程序打开速度慢的三种解决方法 最近好多用户反应,在使用WordPress程序的网站时,不论打开网站前台或是后台,速度都是非常慢.联想近期的GOOGLE断网事件,不难发现,原来是GOOGLE"故障"所致,以致WP内置的字体链接失效://fonts.googleapis.com/css?family=Open+Sans%3A300italic%2C400italic%2C600italic%2C300%2C400%2C600&subset=latin%2Clati

Excel教程:数值为0不显示的三种解决方法介绍

excel表格在我们的日常办公中运用的十分广泛,有时候我们经常需要设置excel数值为0不显示.那么该如何解决呢?本文分享3种解决方法,一起来学习. 方法一:如下图所示,我们想要将excel单元格里面的0不显示出来,如右图所示. 单击"EXCEL选项-高级-此工作表的显示选项-不勾选"在具有零值的单元格中显示零".如下所示: 说明:此方法的设置是针对当前工作表所有的单元格进行设置. 方法二: 第一步:选定数值为0的单元格 1.选择需要将0不显示的单元格区域 2.Ctrl+F查

js闭包for循环总是只执行最后一个值得解决方法

<style> li{ list-style: none;width:40px;height: 40px;text-align:center;line-height: 40px;cursor: pointer; } </style> html代码: <ul id="uls">    <li style="background:#aaa">0</li>    <li style="backgr

开启3个线程依次打印ABC10次

题目: 编写一个程序,开启3个线程,这3个线程的ID分别为A.B.C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示:如:ABCABC-.依次递推. #include <stdio.h> #include <windows.h> #include<iostream> #include <process.h> #include <time.h> using namespace std; HANDLE g_a, g_b,

Java并发:三个线程轮流打印十次abc

方法1:用synchronized.wait.notifyAll实现 public class Main { static boolean t1Running = true; static boolean t2Running = false; static boolean t3Running = false; public static void main(String[] args) throws InterruptedException { final Object lock = new O

Python中循环引用(import)失败的解决方法

原文链接:http://blog.ihuxu.com/the-solution-to-the-problem-of-circular-import-in-python/ 我是采用方案三 "将引用放到函数内部"解决了这个问题.下面为原文. 前言 最近在开发智能家居项目hestia-rpi项目中,由于代码结构层级划分不合理,导致了循环引用(import)module失败的问题,错误如下: Traceback (most recent call last):  File "./ma

CSS3(三)BFC、定位、浮动、7种垂直居中方法

目录 一.BFC与IFC 1.1.BFC与IFC概要 1.2.如何产生BFC 1.3.BFC的作用与特点 二.定位 2.2.relative 2.3.absolute 2.4.fixed 2.5.z-index属性 2.6.菜单 2.7.:target伪类 三.浮动 3.1.float取值 3.2.float的特性 3.3.清除浮动 3.3.1.清除外部浮动 3.3.2.清除内部浮动 四.多种居中办法 4.1.块标签自身水平居中 4.2.块标签内对齐 4.3.垂直居中方法一 4.4.垂直居中方法

CSS3与页面布局学习总结(三)——BFC、定位、浮动、7种垂直居中方法

一.BFC与IFC 1.1.BFC与IFC概要 BFC(Block Formatting Context)即“块级格式化上下文”, IFC(Inline Formatting Context)即行内格式化上下文.常规流(也称标准流.普通流)是一个文档在被显示时最常见的布局形态.一个框在常规流中必须属于一个格式化上下文,你可以把BFC想象成一个大箱子,箱子外边的元素将不与箱子内的元素产生作用. BFC是W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系