java实现SP00LING假脱机输入输出技术模拟

234.jpg
234.jpg

Basic Framework

缓冲技术.png
缓冲技术.png

屏幕快照 2017-12-22 12.09.12.png
屏幕快照 2017-12-22 12.09.12.png
  • 进程调度算法

进程调度采用随机算法,这与进程输出信息的随机性相一致。两个请求输出的用户进程的调度概率各为45%,SP00LING输出进程为10%,这由随机数发生器产生的随机数来模拟决定。

  • 进程状态
    进程有5种状态

    0为可执行态;
    1为等待状态1,表示输出井满,请求输出的用户进程等待;
    2为等待状态2,表示请求输出井空,SP00LING输出进程等待;
    3为等待状态3,表示请求输出井满,请求输出的用户进程等待;
    4为结束态,进程执行完成。进程基本状态有3种,分别为可执行、等待和结束。可执行态就是进程正在运行或等待调度的状态;等待状态又分为等待状态1、等待状态2和等待状态3。
    状态变化的条件为:
    ①进程执行完成时,置为“结束”态。
    ②服务程序在将输出信息送输出井时,如发现输出井已满,将调用进程置为“等待状态1”。
    ③SP00LING进程在进行输出时,若输出井空,则进入“等待状态2”。
    ④SP00LING进程输出一个信息块后,应立即释放该信息块所占的输出井空间,并将正在等待输出的进程置为“可执行状态”。
    ⑤服务程序在输出信息到输出井并形成输出请求信息块后,若SP00LING进程处于等待态,则将其置为“可执行状态”。
    ⑥当用户进程申请请求输出块时,若没有可用请求块时,调用进程进人“等待状态3”。

PCB.java

package Spooling;

public class PCB {
    int ID;//进程标识数
    int status;//进程状态
    int outputFileCount;//要输出的文件数
    int outPut_X;//进程输出时的临时变量
}

requireBlock.java

package Spooling;

public class requireBlock {
    int requireName; //请求进程名
    int length;//本次输出信息长度
    int outputHeadAddress;//信息在输出井的首地址

}

Manage.java

package Spooling;

import java.util.Random;

import javax.swing.JTextArea;
import javax.swing.JTextField;

public class Manage extends Thread{
    PCB pcb[];
    requireBlock requireblock[];
    int buffer[][];
    int outputBufferSpace[];//可使用的输出井buffer空间 
    int outputBufferPointer[][]; //输出井buffer空闲和满指针
    int requireblockNumber;      //requireblock的剩余数量
    int requireblockOutputPointer; //要输出的第一个reqblock指针 
    int requireblockFreePointer; //第一个空闲reqblock指针
    double random;     //用于调度三个进程的控制随机数 
    int output1; //用户进程1已生成的文件数 
    int output2; //用户进程2已生成的文件数 
    int output_1; //用户进程1已输出的文件数
    int output_2; //用户进程2已输出的文件数
    int x;   //随机生成的数据0~9 
    int i;   //临时控制变量
    Random x1;  //辅助生成随机数据x:0~9  
    Spooling spooling; 

    public Manage( Spooling spooling ){//对各进程的数据初始化
        output1 = 0;
        output2 = 0;
        output_1 = 0;
        output_2 = 0;

        pcb = new PCB[4];
        requireblock = new requireBlock[10];
        buffer = new int[3][100];
        outputBufferSpace = new int[3];
        outputBufferSpace[1] = 100;
        outputBufferSpace[2] = 100;

        outputBufferPointer = new int[3][4];
        outputBufferPointer[1][0] = 0;
        outputBufferPointer[2][0] = 0;

        requireblockNumber = 10;

        requireblockOutputPointer = 0;
        requireblockFreePointer = 0;

        x1 = new Random();
        for( i = 0; i < 4; i++ ){
            pcb[ i ] = new PCB();
        }

        for( i = 0; i < 10; i++ ){
            requireblock[ i ] = new requireBlock();
        }

        for( i = 1; i <=3; i++ ){
            pcb[ i ].status = 0;
        }

        this.spooling = spooling;//对各进程的数据初始化完毕  把这个传过来有助于更新界面内容
    }

    public void run(){ //进程调度 
        do{ //while循环

            random = Math.random();//产生一个随机数,控制进程调度,令用户进程概率为45%,Spooling进程为10% 
            if( random <= 0.45 &&  pcb[ 1 ].status == 0 ){ //调度用户进程1
                spooling.textArea4.append( "调度用户进程1\n" );

                try{
                    sleep( 500 );
                }
                catch( InterruptedException e ){
                    e.printStackTrace();
                }
                ///调用用户函数去生成文件填入输出井生成请求块
                output1 = user( 1, output1, spooling.textArea1, spooling.field1 );
            }
            else if( random >0.45 && random <= 0.9 && pcb[ 2 ].status == 0 ){ //调度用户进程2
                spooling.textArea4.append( "调度用户进程2\n" );

                try{
                    sleep( 500 );
                }
                catch( InterruptedException e ){
                    e.printStackTrace();
                }
                output2 = user( 2, output2, spooling.textArea2, spooling.field2 );
            }
            else if( random >0.9 && random <= 1 && pcb[3].status == 0 ){ //调度spooling进程
            spooling.textArea4.append("调度Spooling进程\n");  

                try{
                    sleep( 500 );
                }
                catch( InterruptedException e ){
                    e.printStackTrace();
                }
                spooling1();
            }
        }
        while( pcb[1].status != 4 || pcb[2].status != 4 || pcb[3].status != 4 ); // 当都是结束状态曾程序运行完成 
        spooling.textArea4.append("程序运行完毕\n"); //进程调度结束 
    }

    public int user( int name, int out, JTextArea textarea, JTextField field ){ //用户进程  返回已经生成的文件数目
        pcb[ name ].ID = name;
        pcb[ name ].outputFileCount = Integer.parseInt( field.getText() );
        while( out != pcb[ name ].outputFileCount ){//判断进程所要输出的文件是否输出完毕的while循环 

            outputBufferPointer[ name ][ 1 ] = outputBufferPointer[ name ][ 0 ];

            do{ //判断进程的一个文件是否输出完毕的while循环 
                x = x1.nextInt( 9 );//x为每次随机生成的数据0~9,送入pcb.x 
                pcb[ name ].outPut_X = x;

                if( outputBufferSpace[ name ] == 0 ){ //若输出井buffer满,变为等待状态1,转调度程序
                    pcb[ name ].status = 1;
                    //一个文件的长度是未知的在创建的过程中如果发现井满了要退回去

                    if( outputBufferPointer[ name ][ 0 ] >= outputBufferPointer[ name ][5] ){
                        outputBufferSpace[ name ] = outputBufferSpace[ name ] + outputBufferPointer[ name ][ 0] - outputBufferPointer[ name ][ 1 ];//将空间释放
                    }
                    else{
                        outputBufferSpace[ name ] = outputBufferSpace[ name ] + 100 + outputBufferPointer[ name ][ 0] + outputBufferPointer[ name ][ 1 ];
                    }
                    outputBufferPointer[ name ][ 0 ] = outputBufferPointer[ name ][ 1 ]; //将空间释放
                    textarea.append( "第" + ( out + 1 ) + "个文件缺少输出井" );
                    textarea.append( "进入等待状态1\n" );

                    try{
                        sleep( 500 );
                    }
                    catch( InterruptedException e ){
                        e.printStackTrace();
                    }
                    return out;
                }
                else{//若输出井没满

                    buffer[ name ][ outputBufferPointer[ name ][ 0 ] ] = pcb[ name ].outPut_X;  //进程的输出信息PCB[i].x送buffer[i][ outputBufferPointer[i][0]]  
                    outputBufferSpace[ name ] = outputBufferSpace[ name ] - 1; //输出井空闲个数减1
                    outputBufferPointer[ name ][ 0 ] = ( outputBufferPointer[ name ][ 0 ] + 1 ) % 100;  //修改空缓冲区指针outputBufferPointer[i][0]前进1
                }
            }
            while( x != 0 ); //判断进程的一个文件是否输出完毕的while循环结束

            if( outputBufferPointer[ name ][ 0 ] == 0 ){
                textarea.append( (out + 1)  + " " +  outputBufferPointer[ name ][ 1 ] + " ~ " + " 99 " + outputBufferSpace[ name ] + " "); 
            }
            else{
                textarea.append( (out + 1)  + " " +  outputBufferPointer[ name ][ 1 ] + " ~ " + ( outputBufferPointer[ name ][ 0 ] - 1 ) + " " + outputBufferSpace[ name ] + " " ); 
            }
            try{
                sleep( 500 );
            }
            catch( InterruptedException e ){
                e.printStackTrace();
            }
            out++; //成功生成了一个文件

            //接下来要生成相应的请求块

            if( requireblockNumber == 0 ){//若没有空闲请求输出块,转为等待状态3  

                pcb[ name ].status = 3;
                textarea.append( "缺少请求输出块" );
                textarea.append( "进入等待状态3 \n" );

                try{
                    sleep( 500 );
                }
                catch( InterruptedException e ){
                    e.printStackTrace();
                }
                return out;
            }
            else{ //若有空闲请求输出块 

                requireblock[ requireblockFreePointer ].outputHeadAddress = outputBufferPointer[ name ][ 1 ]; //将文件在输出井的位置填入空闲请求块

                if( outputBufferPointer[ name ][ 0 ] >= outputBufferPointer[ name ][ 1 ] ){ //将文件在输出井的长度填入空闲请求块
                    requireblock[ requireblockFreePointer ].length = outputBufferPointer[ name ][ 0 ] - outputBufferPointer[ name ][ 1 ]; 
                } 
                else{
                    requireblock[ requireblockFreePointer ].length = 100 - outputBufferPointer[ name ][ 1 ] + outputBufferPointer[ name ][ 0 ];
                }
                requireblock[ requireblockFreePointer ].requireName = name; //将进程名i填入请求块
                textarea.append( "获得请求输出块" + Integer.toString( requireblockFreePointer +1 )  + "\n");
                requireblockFreePointer = ( requireblockFreePointer + 1 ) % 10;//修改空闲请求块指针 
                requireblockNumber--;

                if( pcb[ 3 ].status == 2 ){ //若SPOOLING进程是等待状态,则唤醒SPOOLING进程 

                    pcb[ 3 ].status = 0;
                }
            }

        }//判断进程所要输出的文件是否输出完毕的while循环结束 

        textarea.append( "进程" + name + "输出完毕!" );//文件输出完毕,修改状态为结束,转进程调度
        pcb[ name ].status = 4;
        return out; 
    }

    public void spooling1(){

        while( requireblockNumber != 10 ){ //判断请求输出块是否为空的while循环 
            //若请求输出块不为空

            StringBuffer stringBuffer = new StringBuffer( 100 );
            for ( i = 0; i<requireblock[ requireblockOutputPointer ].length; i++) {//按该请求输出信息块requireblock[]的指针requireblockOutputPointer将输出井中的一个文件的内容放入临时buffer1中 
                stringBuffer.append( buffer[ requireblock[ requireblockOutputPointer ].requireName ][ requireblock[ requireblockOutputPointer ].outputHeadAddress] );
                requireblock[ requireblockOutputPointer ].outputHeadAddress = ( requireblock[ requireblockOutputPointer ].outputHeadAddress + 1 )%100;
            }
            if( requireblock[ requireblockOutputPointer ].requireName == 1){
                output_1++;
                spooling.textArea3.append( "User1第" + output_1 + "个文件:");
            }
            else{
                output_2++;
                spooling.textArea3.append( "User2第" + output_2 + "个文件:");
            }
            spooling.textArea3.append( stringBuffer.toString() + "\n" );

            try{
                sleep( 500 );
            } 
            catch( InterruptedException e ){
                e.printStackTrace();
            }

            //释放相应输出井,即修改相应的输出井计数outputBufferSpace
            outputBufferSpace[ requireblock[ requireblockOutputPointer ].requireName ] = outputBufferSpace[ requireblock[ requireblockOutputPointer ].requireName ] + requireblock[ requireblockOutputPointer ].length;
            requireblockOutputPointer = ( requireblockOutputPointer + 1 )%10;
            requireblockNumber++;

            for( int k = 1; k <= 2; k++ ){
                if( pcb[ k ].status == 3 ){ //有等待请求输出块的进程,唤醒没有请求块的进程   一次输出进程完成只能解禁一个请求块所以要完成一个就切断
                    //应该看先是否有等待请求块的进程,这样可以尽早释放相应的井空间
                    pcb[ k ].status = 0;
                    requireblock[ requireblockFreePointer ].outputHeadAddress = outputBufferPointer[ k ][ 1 ];//将文件在输出井的位置填入空闲请求块 
                    if( outputBufferPointer[ k ][ 0 ] >= outputBufferPointer[ k ][ 1 ] ){ //将文件在输出井的长度填入空闲请求块 
                        requireblock[ requireblockFreePointer ].length = outputBufferPointer[ k ][ 1 ];
                    }
                    else{
                        requireblock[ requireblockFreePointer ].length = 100 - outputBufferPointer[ k ][ 1] + outputBufferPointer[ k ][ 0 ];
                    }
                    requireblock[ requireblockFreePointer ].requireName = k;//将进程名i填入请求块

                    if( k ==1 ){
                        spooling.textArea1.append("第" + output1 + "个文件获得请求输出块" + ( Integer.toString( requireblockFreePointer + 1 ) ) + "\n" ); 
                    }
                    if( k == 2 ){
                        spooling.textArea2.append("第" + output2 + "个文件获得请求输出块" + ( Integer.toString( requireblockFreePointer + 1 ) ) + "\n" );
                    }
                    requireblockFreePointer = ( requireblockFreePointer +1 )%10;//修改空闲请求块指针 
                    requireblockNumber--; //空闲请求块数减1

                    if( pcb[ 3 ].status == 2 ){ //若SPOOLING进程是等待状态,则唤醒SPOOLING进程
                        pcb[ 3 ].status = 0;
                    }
                    return; //完成一个就切断, 可能两个都等待请求块,但先满足一个吧  
                }
            }

            for( int k =1; k <=2; k++ ){

                if( pcb[ k ].status ==1 ){ //有等待输出井的进程,唤醒相应进程
                    pcb[ k ].status = 0;
                    return;
                }
            }
        }//判断请求输出块是否为空的while循环结束 

        if( pcb[ 1 ].status ==4 && pcb[ 2 ].status ==4 ){//进程1、2结束后输出进程结束 
            pcb[ 3 ].status = 4;
            spooling.textArea3.append( " Spooling输出进程结束" );
            return;
        }
        else{
            spooling.textArea3.append( "调度spooling输出程序,请求块空,输出进程转入状态2\n" );
            pcb[ 3 ].status = 2;
        }
    }
}

Spooling.java

package Spooling;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

public class Spooling extends JFrame implements ActionListener{
    JPanel panel1;
    JPanel panel2;
    JPanel panel3;
    JTextField field1;
    JTextField field2;
    JScrollPane p1;
    JScrollPane p2;
    JScrollPane p3;
    JScrollPane p4;
    JTextArea textArea1;
    JTextArea textArea2;
    JTextArea textArea3;
    JTextArea textArea4;
    JButton button;
    Manage manage;

    public Spooling(){
    //界面构造函数
        manage = new Manage( this );
        Container container = this.getContentPane();
        container.setLayout( new BorderLayout() );

        field1 = new JTextField( 3 );//设置panel1
        field2 = new JTextField( 3 );

        button = new JButton( "运行" );
        button.addActionListener( this );

        panel1 = new JPanel();
        panel1.setLayout( new FlowLayout() );

        panel1.add( new JLabel( "用户进程1文件数:", SwingConstants.RIGHT ) );
        panel1.add( field1 );
        panel1.add( new JLabel( "用户进程2文件数:", SwingConstants.RIGHT) );
        panel1.add( field2 );
        panel1.add( button );
        //设置panel1完毕

        textArea1 = new JTextArea( 80,100 );//设置panel2
        textArea2 = new JTextArea( 112,400 );

        textArea1.append( "用户进程1的文件生成情况及状态变换\n文件序号  位    置  剩余空间    状态\n" );
        textArea2.append("用户进程2的文件生成情况及状态变换\n文件序号   位    置  剩余空间    状态\n");

        p1 = new JScrollPane( textArea1 );
        p2 = new JScrollPane( textArea2 );

        panel2 = new JPanel();
        panel2.setLayout ( new GridLayout( 1,2 ) );
        panel2.add( p1 );
        panel2.add( p2 );
        //设置panel2完毕

        textArea3 = new JTextArea( 15,400 );//设置panel3
        textArea4 = new JTextArea( 15,150 );
        textArea3.append( "打印输出\n" );
        textArea4.append("主程序调度\n");

        p3 = new JScrollPane( textArea3 );
        p4 = new JScrollPane( textArea4 );

        panel3 = new JPanel();
        panel3.setLayout( new GridLayout( 1,2 ) );
        panel3.add( p3 );
        panel3.add( p4 );

        container.add( panel1, BorderLayout.NORTH );//设置窗口
        container.add( panel2 ,BorderLayout.CENTER );
        container.add( panel3, BorderLayout.SOUTH );

        this.setSize( 1200,600 );
        this.setLocation( 100,100 );
        this.setTitle( "Spooling" );
        this.setVisible( true );
        this.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );//设置窗口完毕
    }

    public void actionPerformed( ActionEvent e ){
        manage.start();
    }

    public static void main( String args[] ){
        Spooling spooling = new Spooling();
    }
}

Running Effect

屏幕快照 2017-12-22 12.09.01.png
屏幕快照 2017-12-22 12.09.01.png

Source Download

Please click the address->spooling

Summarize

SP00LING 输出模拟系统主控流程图.jpg
SP00LING 输出模拟系统主控流程图.jpg

SP00LING 输出服务程序由两个用户进程调用流程图.jpg
SP00LING 输出服务程序由两个用户进程调用流程图.jpg

SPOOLING 输出进程流程图.jpg
SPOOLING 输出进程流程图.jpg

原文地址:www.iooy.com

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容