一个同步打印机的简单实现

  • 内部机制

打印机内部设有缓冲区,当有新任务来到的时候,打印机只是简单的从任务中取出需要打印的消息,然后将其存入自身的缓冲区,然后返回,具体的打印任务交给一个线程来处理,打印线程从缓冲区中读消息,打印,然后等待,直到有别的线程唤醒它。其结构如图所示:

 

syncprinter  

 

  • 单例模式

作为一个系统硬件的模拟,在一个项目中有一个打印机就够用了,在项目中任何需要打印消息的地方,需要使用SyncPrinter.getInstance() 静态方法获取此刻的SyncPrinter实例,并使用print(String message)进行打印。(关于单例模式的细节可以参考别的设计模式的书籍)

  • 同步打印

当然,打印的线程不需要等待打印机缓慢的打印结束,另一种做法是:当打印机收到打印任务后,将此任务放入自己的缓冲区,然后迅速返回,调用打印机的线程可以立即开始接下来的动作,而同时,打印机可以另起一个线程,来打印存储在自己缓冲区中的数据,从而做到同步打印。

缓冲区在本例中实现为一个队列(一个先进先出的数据结构FIFO),队列中的数据总是从尾部插入,从头部被取出。

  • 实现

 

 

 

本例使用JAVA语言实现,当然,任何其他支持线程的语言也可以完成这个任务。

import java.util.LinkedList;
import java.util.List;

public class SyncPrinter {
    private static SyncPrinter instance;
    private List msgQueue;
    private PrintWorker printWorker;

    public static SyncPrinter getInstance(){//单例模式,任何时候系统中只有一个类实例
        synchronized(SyncPrinter.class){
            if(instance == null){
                instance = new SyncPrinter();
            }
        }
        return instance;
    }

    private SyncPrinter(){
        msgQueue = new LinkedList();
        printWorker = new PrintWorker();
        printWorker.start();
    }

    public void print(String message){// 对外公开的使用打印机的接口
        synchronized(msgQueue){
            msgQueue.add(message);
            msgQueue.notify();
        }
    }

    private class PrintWorker extends Thread{//一个执行打印任务的内部类的封装
        private boolean loop = true;
        private Object lock = new Object();

        public void stopPrinter(){
        }

        public void run(){
            while(loop){
                String msg = "";
                synchronized(msgQueue){
                    try {
                        msgQueue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // IO
                msg = (String)msgQueue.remove(0);
                if(msg != null){
                    System.out.println(msg);
                }
            }
        }
    }// 对于这个死循环的控制可以做在外部,也可以做在这个类中,通过一个方法来控制,如stopPrinter()
}

 

 

 

  • 小结

这个打印机的意义或许不是很大,但是让快速的线程等待一个缓慢的IO过程是不合理的,同时,这是一种分工的思想,而这种互不干涉,各司其职的做法正是面向对象的核心。

借此文来对面向对象的设计原则做一个巩固,同时也可能会帮助其他需要使用同步打印机的人。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值