
234.jpg
Basic Framework

緩沖技術.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
Source Download
Please click the address->spooling
Summarize

SP00LING 輸出模擬系統主控流程圖.jpg

SP00LING 輸出服務程序由兩個用戶進程調用流程圖.jpg

SPOOLING 輸出進程流程圖.jpg
原文地址:www.iooy.com