zoukankan      html  css  js  c++  java
  • 多个线程实现顺序打印数据,(可自定义线程一次打印数量和总数量)

      最近看到一道面试题:让3个线程顺序打印数字,如线程1打印1-5,线程2打印6-10,线程3打印11-15,然后是线程1打印16-20...一直打印到75结束。

      这到题主要问题有两点:

        第一点是不能让线程打印的过程中出现其他线程

        第二点是要实现线程进入的过程是有序的,如上123123..这样。

      我先是把基本的功能实现了,后来发现可以改造一下,做成可扩展的,即每次打印的数量可自定义,总的数量可自定义,并且保证线程的顺序是有序的,下面是具体代码:

      PrintQueue.java 文件,同步线程,控制打印顺序,也是最主要的方法

    package com.cky;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    public class PrintQueue {
        public int targetNum=0;    //要打印的目标数量
        public int printOnce=0;    //一次要打印的次数
        private int nowNum=1;        //目前打印到的数量
        /**
         * 
         * @param targetNum    要打印的目标数量
         * @param printOnce 一次要打印的次数
         */
        public PrintQueue(int targetNum, int printOnce) {
            super();
            this.targetNum = targetNum;
            this.printOnce = printOnce;
        }
    
        private int nextThreadNum=0;//下次要执行线程的下标
        private int threadCount=0;//总的线程数量
        
        //map集合,存放线程,键是具体线程,值存放线程打印的顺序
        private Map<Thread,Integer> threads=new LinkedHashMap<Thread,Integer>();
        
        //添加线程
        public void setThread(Thread thread) {
            threads.put(thread, threadCount);
            threadCount++;
        }
        //运行线程
        public void run() {
            for (Thread thread : threads.keySet()) {
                thread.start();
            }
        }
        
        public synchronized void printNum() throws InterruptedException {
            //获取当前线程
            Thread currentThread=Thread.currentThread();
            //获取当前线程坐标
            int currentNum=threads.get(currentThread);
            //判断是否为期望线程
            if(currentNum==nextThreadNum) {
                for(int i=0;i<printOnce;i++) {
                    System.out.println("当前线程:"+currentThread.getName()+":"+nowNum++);
                    if(nowNum>targetNum) {
                        System.out.println("工作完成");
                        this.wait();
                    }
                }
                //期望线程名+1
                nextThreadNum=(++nextThreadNum)%threadCount;
            }
        }
        
    }

      RunTest.java  很简单的Runable接口实现,功能就是请求打印

    package com.cky;
    
    class RunTest implements Runnable{
        PrintQueue ps;
        public RunTest(PrintQueue ps ) {
            this.ps=ps;
        }
        @Override
        public void run() {
            try {
                while(true) {
                    ps.printNum();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    ThreadDemo.java 测试类

    package com.cky;
    
    public class ThreadDemo {
        public static void main(String [] args) {
            //设置一共打印20个,每个线程一次只打印3个
         PrintQueue ps
    =new PrintQueue(20, 3);
         //添加线程 ps.setThread(
    new Thread(new RunTest(ps),"王大锤")); ps.setThread(new Thread(new RunTest(ps),"张全蛋")); ps.setThread(new Thread(new RunTest(ps),"二狗")); ps.run(); } }

    执行结果:

  • 相关阅读:
    easyui_1
    JSONOBJECT
    基础回顾—list遍历4种
    <input type=file>上传唯一控件
    window.open
    poi--导入
    java字符串的替换
    一、IIS搭建前端静态模板_资源加载问题
    一、ASP.NET Iframework_SignalR集线器类(v2)
    一、ASP.NET Iframework_SignalR永久连接类(v2)
  • 原文地址:https://www.cnblogs.com/chenkeyu/p/7944879.html
Copyright © 2011-2022 走看看