java基础_设计模式_命令模式二(以计算机读取内存和硬盘为例)
来源:互联网 发布:低价顶级域名 编辑:程序博客网 时间:2024/05/29 19:03
我是野猪。
题目的要求如下:
“计算机系统中存在多个具有I/O操作的组件,比如内存、硬盘、声卡等;这些I/O组件都具有读和写的操作。
假设计算机系统要对这些I/O组件的操作统一管理,并把它们的操作(由用户代码触发)存放到系统中的唯一的一个队列中。
假设当前系统有两个线程,可以通过一个统一的接口处理队列中命令,但只能互斥的访问该队列;
此外,线程处理一个命令之后,为了便于观看,都随机的等待1-4s。
请选择合适的模式来模拟这个过程。PS:不考虑I/O组件自身读写的互斥问题,输出一跳语句来表示读、写操作即可。”
分析过程:
1.创建具体的组件,比如RAM和DIESK(内存和硬盘);
2.创建具体的指令;
3.创建存放指令的队列(为保证只能互斥访问该队列设计成单列模式);
4.运行时,指令放入队列中,创建线程,启动线程,查看运行结果。
1.创建组件(抽象父类和其有具体实现的子类):
/** * 代指计算机中任何一个器件 * 功能输入和输出 * 真正能执行组件读、写操作的是组件本身; */public abstract class Compent { protected final String name; public Compent(String name) { this.name = name; } public abstract void read(); public abstract void write();}
/** * 具体的控件 * Ram 内存 */public class RAM extends Compent { public RAM(String name) { super(name); } @Override public void read() { System.out.println(name + " is reading"); } @Override public void write() { System.out.println(name + " is writtng"); }}
/** * 具体控件 DIESK */public class DIESK extends Compent { private DIESK(String name) { super(name); } @Override public void read() { System.out.println(name + " is reading"); } @Override public void write() { System.out.println(name + " is writting"); }}2.创建命令(命令的父类和具体到每一个I/O组件上的读写命令):
通过一个统一的接口处理队列中命令;代码如下,很简单:
/** * 接口 职责就是执行命令 */public interface Command { void execute();}
/** * 具体的硬盘读命令 */public class DieskReadCommand implements Command { Compent diesk; public DieskReadCommand(Compent compent) { this.diesk = compent; } @Override public void execute() { //执行什么?执行的是内存的读操作 diesk.read(); }}
/** * 具体的硬盘写命令 */public class DieskWriteCommand implements Command { Compent diesk; public DieskWriteCommand(Compent compent) { this.diesk = compent; } @Override public void execute() { //执行什么?执行的是内存的读操作 diesk.write(); }}
/** * 具体的内存读命令 */public class RamReadCommand implements Command { Compent ram; public RamReadCommand (Compent compent) { this.ram = compent; } @Override public void execute() { //执行什么?执行的是内存的读操作 ram.read(); }}
/** * 具体的内存的写命令 */public class RamWriteCommand implements Command { Compent ram; public RamWriteCommand(Compent compent) { this.ram = compent; } @Override public void execute() { //执行什么?执行的是内存的读操作 ram.write(); }}
3.使用单例模式创建存放指令的队列(队列应该具有插入和获取指令的方法):
import java.util.LinkedList;import java.util.Queue;/** * 存放具体操作命令的队列 * 线程不和任务直接沟通合适传话人 */public class CommandQueueSingleTon { private static CommandQueueSingleTon commandQueueSingetion = null; //存放命令的队列 之所以使用linkedlist 因为命令的读写操作频繁 Queue<Command> commandQueue = new LinkedList<Command>(); //1.私有构造 private CommandQueueSingleTon() { } //2.对外暴露方法(获取一个有权限的引用指向这个实例) public static CommandQueueSingleTon getQueueSinglton() { if (commandQueueSingetion == null) { synchronized (CommandQueueSingleTon.class) { if (commandQueueSingetion == null) { commandQueueSingetion = new CommandQueueSingleTon(); } } } return commandQueueSingetion; } //4.以上是单例的书写方式 下面就是提供方式让命令插入队列和取出队列 public void insertCommand(Command cmd) { commandQueue.add(cmd); } public Command getCommand() { if (commandQueue != null) { Command command = commandQueue.poll(); return command; } else { return null; } }}4.main函数中测试,基本流程也是①创建I/O组件;②根据组件创建具体的命令;③命令入队;④创建两个线程,从队列中读取调用命令:
/** * 测试 */public class Test { public static void main(String[] args) { //1.执行命令的控件 Compent ram = new RAM("RAM"); Compent diesk = new RAM("Cpu"); //2.传话人 Command ramReadCommand = new RamReadCommand(ram); Command ramWriteCommand = new RamWriteCommand(ram); Command dieskReadCommand = new DieskReadCommand(diesk); Command dieskWritteCommand = new DieskWriteCommand(diesk); //3.命令入列 CommandQueueSingleTon commandQueue = CommandQueueSingleTon.getQueueSinglton(); commandQueue.insertCommand(ramReadCommand); commandQueue.insertCommand(ramWriteCommand); commandQueue.insertCommand(dieskReadCommand); commandQueue.insertCommand(ramWriteCommand); commandQueue.insertCommand(dieskWritteCommand); //4。创建线程 Runnable commandProcessor1 = new CommandProcess(); Runnable commandProcessor2 = new CommandProcess(); //start 并不是启动线程而是代表只是把线程放到cpu执行队列中 Thread thread1 = new Thread(commandProcessor1); thread1.start(); Thread thread2 = new Thread(commandProcessor2); thread2.start(); } static class CommandProcess implements Runnable { @Override public void run() { while (true) { try { //随机睡上1-4s Random RAND = new Random(1); Thread.sleep(RAND.nextInt(4*1024)); CommandQueueSingleTon queueSinglton = CommandQueueSingleTon.getQueueSinglton(); Command command = queueSinglton.getCommand(); if (command != null) { command.execute(); } else { break; } } catch (Exception e) { e.printStackTrace(); } } } }}ps:这段代码比较简单,其中用到的随机数和伪随机数的概念在另一篇文章有简单介绍,线程的介绍也是,大家有需要的话可以自行阅览。
如果对以上代码有疑问的话,希望大家能随时指出。
阅读全文
2 0
- java基础_设计模式_命令模式二(以计算机读取内存和硬盘为例)
- java基础_设计模式_单例模式二(详解6种写法)
- java基础_设计模式_单例模式
- java设计模式_命令模式
- java设计模式_命令模式
- java设计模式_命令模式
- java设计模式15_命令模式
- Java设计模式_(行为型)_命令模式
- 设计模式_基础
- java基础_设计模式_装饰者模式
- java基础_设计模式_抽象工厂模式
- 设计模式_命令模式
- 设计模式_命令模式
- 设计模式_命令模式
- 设计模式_命令模式
- Java设计模式(一)_单例设计模式
- java基础_设计模式_设计基础(小鸭子游戏)
- Java设计模式_单例模式
- CoordinatorTabLayout
- CCF CSP 201409-1 相邻数对
- linux(ubuntu)下安装和启动kafka以及若干坑
- os.path.dirname/abspath函数
- 在Pypi上发布自己的Python包
- java基础_设计模式_命令模式二(以计算机读取内存和硬盘为例)
- 记一次maven的Missing artifact问题
- 放弃new,字面量让js更优美和谐简洁
- 抓取DHCP包
- 【C#】图像滤镜(一):图像平滑
- 如何学习、了解kubernetes
- Spring MVC使用拦截器实现日志记录
- ListView和RecyclerView点击返回顶部
- AJAX方法介绍