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種,分別為可執行、等待和結束??蓤绦袘B就是進程正在運行或等待調度的狀態;等待狀態又分為等待狀態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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容