动态分区分配(基于Java语言的可视化展示)

目的: 熟悉内存的分配与回收过程;理解在不同的管理方式下,如何实现内存空间的分配与回收;通过实验,掌握动态分区分配方式中的数据结构、分配算法、动态分区存储管理方式其实现过程。
要求: 分别实现四种分配算法:首次适应、循环首次适应、最佳适应和最坏适应。

(1)数据结构
       采用链表表示内存使用情况,链表中的结点可以给出对应的某块内存区域的信息,如起始地址、大小、使用情况(是否空闲)、所装入的进程名等。

  • 设计一个空闲分区链表,用以表示当前内存使用情况,在进行内存分配时,系统优先使用空闲区低端的空间。(也可以设置两个链表,一个是空闲分区,一个是已分配分区)
  • 利用一个进程申请队列以及进程完成后的释放顺序,实现主存的分配和回收。

(2)内存分配

  • 动态输入构造空闲区表,并显示打印构造好的空闲分区表;
  • 根据到达进程的申请,实施内存分配,并返回分配所得内存首址;
  • 分配完后,调整空闲分区表(即扣除分配部分),并显示调整后的空闲分区表;
  • 若分配失败,返回分配失败信息。

(3)内存回收

  • 进程运行结束后,回收相应的内存,按内存回收的四种情况进行内存回收;

(4)输入

  • 除操作系统占用的内存外,可用内存大小 n(整数);
  • 进程申请队列(输入各进程名、申请的空间大小、到达时间、运行时间等,获得内存后按先来先服务算法调度运行)。
    例如:假设初始状态下,可用的内存空间为 640KB,并有下列的请求序列:
    进程 1,130KB,0,5
    进程 2,60KB,3,6
    进程 3,100KB,2,8
    进程 2,60KB,5,10
    进程 5,200KB,8,2
    ……

(5)实现

Job.java

package com.test;

import java.util.Objects;

/**
 * @program: untitled
 * @description: 作业类
 * @author: YOUNG
 * @create: 2020-12-04 16:21
 */
public class Job {
    
    
    //起始地址
    private int id;
    private int size;
    //剩余工作时间
    private int time;

    public int getTime() {
    
    
        return time;
    }

    public int getId() {
    
    
        return id;
    }


    public int getSize() {
    
    
        return size;
    }


    public Job(int id, int size,int time) {
    
    
        this.id = id;
        this.size = size;
        this.time = time;
        System.out.println(this.toString());
    }

    public void run(){
    
    
        if (this.time>0)
        this.time-=1;
    }

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Job job = (Job) o;
        return id == job.id && size == job.size;
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(id, size);
    }

    @Override
    public String toString() {
    
    
        return "Job{" +
                "id=" + id +
                ", size=" + size +
                ", time=" + time +
                '}';
    }
}

Memory.java

package com.test;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/**
 * @program: untitled
 * @description:
 * @author: YOUNG
 * @create: 2020-12-04 15:43
 */
public class Memory {
    
    
    //内存大小
    private final int size;

    //空闲大小
    private int unusedSize;

    //已分配大小
    private int usedSize;
    //所有块头指针
    private Block blockPointer;
    //空闲块链表
    private final LinkedList<Block> IdleLinkedList;
    //已分配块链表
    private final LinkedList<Block> AllocatedLinkedList;
    //已经运行时间
    private int time = 0;
    //
    private String flag;
    private boolean startFlag = false;
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();


    public Memory(int size) {
    
    
        this.size = size;
        this.unusedSize = size;
        this.usedSize = 0;
        Block firstBlock = new Block(size, 0);
        this.blockPointer = firstBlock;
        this.IdleLinkedList = new LinkedList<>();
        IdleLinkedList.add(firstBlock);
//        第一次添加内存块只有一个没必要排序
//        IdleLinkedList.sort(Comparator.comparingInt(reBlock -> reBlock.headAddress));
        this.AllocatedLinkedList = new LinkedList<>();
    }

    public void start() {
    
    
        new Thread(() -> {
    
    
            //消亡内存块队列
            ArrayList<Integer> blockIds = new ArrayList<>();
            //作业准备队列
            ArrayList<Job> readyJobs = new ArrayList<>();
            int i = 3;
            while (true) {
    
    
                //更新页面
                My.getOwm().updateUI();
                //装载作业
                if (time == 0)
                    readyJobs.add(new Job(1, 130, 5));
                if (time == 3)
                    readyJobs.add(new Job(2, 60, 6));
                if (time == 2)
                    readyJobs.add(new Job(3, 100, 8));
                if (time == 5)
                    readyJobs.add(new Job(2, 60, 10));
                if (time == 8)
                    readyJobs.add(new Job(5, 200, 12));
                if (time == 12)
                    readyJobs.add(new Job(6, 150, 5));
                if (time == 16)
                    readyJobs.add(new Job(7, 80, 5));
                if (time == 19)
                    readyJobs.add(new Job(8, 80, 5));
                //从准备队列将作业装入到内存块中
                readyJobs.removeIf(job -> add(flag, job));
                try {
    
    
                    Thread.sleep(500);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                //第二次更新页面,显示装入的过程
                My.getOwm().updateUI();
                //运行1s
                AllocatedLinkedList.forEach(block -> {
    
    
                    block.jobbing.run();
                    if (block.jobbing.getTime() == 0) {
    
    
                        blockIds.add(block.id);
                    }
                });
                blockIds.forEach(this::remove);
                blockIds.clear();
                try {
    
    
                    Thread.sleep(500);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                time++;
                if (AllocatedLinkedList.size() == 0)
                    if (i != 0)
                        i--;
                    else
                        break;
                if (startFlag) {
    
    
                    My.getOwm().getNextButton().setEnabled(true);
                    lock.lock();
                    try {
    
    
                        condition.await();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    lock.unlock();
                }
            }
            My.getOwm().getChangeButton().setEnabled(true);
            My.getOwm().getFFButton().setEnabled(true);
            My.getOwm().getNFButton().setEnabled(true);
            My.getOwm().getBFButton().setEnabled(true);
            My.getOwm().getWFButton().setEnabled(true);
        }).start();
    }

    //起始空闲块
//    private Block initialIdleBlock;

    //最终空闲块
//    private Block finalIdleBlock;

    //起始已分配块
//    private Block initialAllocatedBlock;

    //最终已分配块
//    private Block finalAllocatedBlock;

    //内存分区块
    private class Block {
    
    
        //id
        private int id;
        //起始地址
        private int headAddress;
        //大小
        private int size;
        //空闲状态
        private boolean isFree;
        //前驱指针
        private Block front;
        //后继指针
        private Block next;
        //作业
        private Job jobbing;

        public Block(Job jobbing, int headAddress) {
    
    
            this.id = jobbing.getId();
            this.size = jobbing.getSize();
            this.isFree = false;
            this.jobbing = jobbing;
            this.headAddress = headAddress;
        }

        public Block(int size, int headAddress) {
    
    
            this.size = size;
            this.isFree = true;
            this.headAddress = headAddress;
        }

        public void setJobbing(Job jobbing) {
    
    
            this.id = jobbing.getId();
            this.size = jobbing.getSize();
            this.isFree = false;
            this.jobbing = jobbing;
        }

        @Override
        public String toString() {
    
    
            return "Block{" +
                    "id=" + id +
                    ", size=" + size +
                    ", isFree=" + isFree +
                    ", jobbing=" + jobbing +
                    '}';
        }

    }

    public synchronized boolean add(String flag, Job job) {
    
    
        //装入内存的作业大小小于等于剩余内存大小
        if (job.getSize() <= this.unusedSize) {
    
    
            if (flag.equals("FF") || flag.equals("NF")) {
    
    
                for (Block block : IdleLinkedList) {
    
    
                    if (loadJob(job, block)) return true;
//                    if (block.size > job.getSize()) {//可用块大小大于作业大小
//                        //从可用块中分出作业大小的内存块,然后装入作业
//                        Block PreparedBlock = new Block(job, block.headAddress);
//                        //更新起始地址
//                        block.headAddress += PreparedBlock.size;
//                        block.size -= PreparedBlock.size;
//                        PreparedBlock.front = block.front;
//                        //无头结点的弊端
//                        if (block.front != null)
//                            block.front.next = PreparedBlock;
//                        block.front = PreparedBlock;
//                        PreparedBlock.next = block;
//
//                        AllocatedLinkedList.add(PreparedBlock);
//                        AllocatedLinkedList.sort(Comparator.comparingInt(reBlock -> reBlock.headAddress));
//
//                        //更新内存空闲大小和内存已分配大小
//                        updateUnusedSizeAndUsedSize(PreparedBlock, "add");
//                        //更新所有内存块头指针
//                        updateBlockPointer();
//
//                        return true;
//                    } else if (block.size == job.getSize()) {//可用块大小正好等于作业大小,直接装入
//                        //在foreach不应该remove元素,但这里可以使用,是一个陷阱
//                        IdleLinkedList.remove(block);
//                        block.setJobbing(job);
//                        AllocatedLinkedList.add(block);
//                        AllocatedLinkedList.sort(Comparator.comparingInt(reBlock -> reBlock.headAddress));
//
//
//                        //更新内存空闲大小和内存已分配大小
//                        updateUnusedSizeAndUsedSize(block, "add");
//                        //更新所有内存块头指针
//                        updateBlockPointer();
//
//                        return true;
//                    }
                }

                return false;
            } else if (flag.equals("BF") || flag.equals("WF")) {
    
    
                Block block = null;
                //最佳:距离应该大于总内存大小
                //最坏:距离应该小于0
                int distance = flag.equals("BF") ? size + 1 : -1;

                for (Block reBlock : IdleLinkedList) {
    
    
                    if (reBlock.size >= job.getSize()) {
    
    //块大小>=作业大小,块可用
                        if (flag.equals("BF")) {
    
    //是BF算法
                            if (reBlock.size - job.getSize() < distance) {
    
    
                                block = reBlock;
                                distance = block.size - job.getSize();
                            }
                        } else {
    
    //只能是WF算法
                            if (reBlock.size - job.getSize() > distance) {
    
    
                                block = reBlock;
                                distance = block.size - job.getSize();
                            }
                        }
                    }
                }
                if (block != null) {
    
    
                    System.out.println(block.size);
                    return loadJob(job, block);
                } else
                    return false;
            }
        }
        return false;
    }

    private boolean loadJob(Job job, Block block) {
    
    
        if (block.size > job.getSize()) {
    
    //可用块大小大于作业大小
            //从可用块中分出作业大小的内存块,然后装入作业
            Block PreparedBlock = new Block(job, block.headAddress);
            //更新起始地址
            block.headAddress += PreparedBlock.size;
            block.size -= PreparedBlock.size;
            PreparedBlock.front = block.front;
            //无头结点的弊端
            if (block.front != null)
                block.front.next = PreparedBlock;
            block.front = PreparedBlock;
            PreparedBlock.next = block;

            AllocatedLinkedList.add(PreparedBlock);
            AllocatedLinkedList.sort(Comparator.comparingInt(reBlock -> reBlock.headAddress));

            //更新内存空闲大小和内存已分配大小
            updateUnusedSizeAndUsedSize(PreparedBlock, "add");
            //更新所有内存块头指针
            updateBlockPointer();

            return true;
        } else if (block.size == job.getSize()) {
    
    //可用块大小正好等于作业大小,直接装入
            //在foreach不应该remove元素,但这里可以使用,是一个陷阱
            IdleLinkedList.remove(block);
            block.setJobbing(job);
            AllocatedLinkedList.add(block);
            AllocatedLinkedList.sort(Comparator.comparingInt(reBlock -> reBlock.headAddress));


            //更新内存空闲大小和内存已分配大小
            updateUnusedSizeAndUsedSize(block, "add");
            //更新所有内存块头指针
            updateBlockPointer();

            return true;
        }
        return false;
    }

    public synchronized boolean remove(int id) {
    
    

        for (Block block : AllocatedLinkedList) {
    
    
            if (block.id == id) {
    
    
                AllocatedLinkedList.remove(block);
                //更新内存信息
                updateUnusedSizeAndUsedSize(block, "remove");
                block.id = 0;
                block.jobbing = null;
                block.isFree = true;
                //合并空闲分区
                if (block.front != null && block.front.isFree) {
    
    
                    block.front.size += block.size;
                    //block.front.next=block.next;
                    if (block.next != null && block.next.isFree) {
    
    //左右块都是空闲块
                        IdleLinkedList.remove(block.next);

                        block.front.size += block.next.size;
                        block.front.next = block.next.next;
                        if (block.next.next != null) {
    
    
                            block.next.next.front = block.front;
                        }

                        block.next.next = null;
                        block.next.front = null;
                        block.next = null;
                        block.front = null;

                        return true;
                    } else if (block.next != null)
                        block.next.front = block.front;
                    ///左块空闲,右块不是
                    block.front.next = block.next;

                    block.next = null;
                    block.front = null;
                    return true;
                    ///
                } else if (block.next != null && block.next.isFree) {
    
    //右块空闲,左块不是
                    IdleLinkedList.remove(block.next);
                    block.size += block.next.size;
                    Block p = block.next;
                    block.next = p.next;
                    if (p.next != null) {
    
    
                        p.next.front = block;
                    }
                    IdleLinkedList.add(block);
                    if (flag != null && flag.equals("FF"))
                        IdleLinkedList.sort(Comparator.comparingInt(reBlock -> reBlock.headAddress));
                    p.next = null;
                    p.front = null;
                    return true;
                } else {
    
    //左右都不是空闲块
                    IdleLinkedList.add(block);
                    if (flag != null && flag.equals("FF"))
                        IdleLinkedList.sort(Comparator.comparingInt(reBlock -> reBlock.headAddress));
                    return true;
                }
            }
        }
        return false;
    }

    private void updateUnusedSizeAndUsedSize(Block block, String flag) {
    
    
        if (flag.equals("add")) {
    
    
            this.usedSize += block.size;
            this.unusedSize -= block.size;
        } else if (flag.equals("remove")) {
    
    
            this.usedSize -= block.size;
            this.unusedSize += block.size;
        }
    }

    private void updateBlockPointer() {
    
    
        if (blockPointer.front != null)
//            while (blockPointer.front!=null)
            this.blockPointer = blockPointer.front;

    }


    public Image drawImage() {
    
    
        // 创建内存图像
        int width = this.size + 5 + 5, height = 150 + 5 + 5;
        BufferedImage image = new BufferedImage(width, height + 20 * 2, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();

        // 填充矩形区域
        g.setColor(new Color(255, 255, 255));
        g.fillRect(0, 0, width, height + 20 * 2);
        //画外边框
        g.setColor(new Color(0, 0, 0));
        g.drawRect(1, 1, width - 2, height - 2);

        //画内存块
        Block p = blockPointer;
        int x = 5;
        while (p != null) {
    
    
            if (p.isFree)
                g.setColor(new Color(120, 190, 60));
            else
                g.setColor(new Color(255, 155, 155));
            g.fillRect(x, 5, p.size - 1, height - 10);
            g.setColor(new Color(0, 0, 0));
            g.fillRect(x + p.size - 1, 5, 1, height - 10);
            //写内存块大小
            g.drawString(p.size + "KB", x + 1, (height - 10) / 2 + 5);
            //写内存块首地址
            if (p.isFree)
                g.drawString(p.headAddress + "", x + 1, 15 + 1);
            else {
    
    
                g.setColor(new Color(18, 80, 11));
                g.drawString(p.headAddress + ": job" + p.jobbing.getId(), x + 1, 15 + 1);
                g.drawString(p.jobbing.getTime() + "s", x + 1, 15 + 1 + 20);
            }
            x += p.size;
            p = p.next;
        }
        //画内存大小
        g.drawString("used:" + this.usedSize + "KB / " + "size:" + this.size + "KB", width - 150, height + 20);
        g.drawString("runtime:" + this.time + 's', width - 100, height + 20 * 2);
        g.dispose();
        return image;
    }

    public void setFlag(String flag) {
    
    
        this.flag = flag;
    }

    public Condition getCondition() {
    
    
        return condition;
    }

    public Lock getLock() {
    
    
        return lock;
    }

    public void setStartFlag(boolean startFlag) {
    
    
        this.startFlag = startFlag;
    }
}

My.java

package com.test;

import javax.swing.*;
import java.awt.*;

/**
 * @program: untitled
 * @description:
 * @author: YOUNG
 * @create: 2020-12-04 15:44
 */

public class My {
    
    
    private static My my;
    private final JFrame jFrame = new JFrame("动态内存分区");
    private final Box centerBox = Box.createVerticalBox();
    private final Box southBox = Box.createVerticalBox();
    private final JPanel southJPanel = new JPanel(new GridLayout(3,1));
    private final JPanel centerJPanel = new JPanel(new GridLayout(2,1));
    private final JPanel jobJPanel = new JPanel(new GridLayout(1,5));
    private final JPanel buttonJPanel = new JPanel(new GridLayout(1,4));
    private final JPanel changeButtonJPanel = new JPanel(new GridLayout(1,2));
    private final JPanel imagePanel = new JPanel();
    private final JButton FFButton = new JButton("首次适应");
    private final JButton NFButton = new JButton("循环首次适应");
    private final JButton BFButton = new JButton("最佳适应");
    private final JButton WFButton = new JButton("最坏适应");
    private final JButton okJobButton = new JButton("创建作业");
    private final JButton changeButton = new JButton("自动演示");
    private final JButton nextButton = new JButton("下一步");

    private final JLabel jobIdLabel = new JLabel("作业ID:");
    private final JLabel jobSizeLabel = new JLabel("作业大小:");
    private final TextArea centerTextArea  = new TextArea ("0,new Job(name:1, size:130, runtime:5)\n" +
            "3,new Job(name:2, size:60, runtime:6)\n" +
            "2,new Job(name:3, size:100, runtime:8)\n" +
            "5,new Job(name:2,size: 60, runtime:10)\n" +
            "8,new Job(name:5, size:200, runtime:12)\n" +
            "12,new Job(name:6, size:150,runtime:5)\n" +
            "16,new Job(name:7, size:80, runtime:5)\n" +
            "19,new Job(name:8, size:80, runtime:5)\n");
    private final JTextField jobIdTextField   = new JTextField ("");
    private final JTextField jobSizeTextField   = new JTextField ("");
    //默认可以不生成对象,为了防止程序崩溃,先搞一个
    private  Memory memory = new Memory(640);
    private boolean model =false;

    public Memory getMemory() {
    
    
        return memory;
    }

    private My(){
    
    };
    public static My getOwm(){
    
    
        if (my==null)
            my = new My();
            return my;
    }
    public void init() {
    
    
//        imagePanel.add(new JLabel(new ImageIcon(memory.drawImage())));
        jFrame.setBounds(0, 0, 1920-500, 700);

        centerJPanel.add(imagePanel);
        centerJPanel.add(centerTextArea);
        centerBox.add(centerJPanel);
        jFrame.add(centerBox, BorderLayout.CENTER);


        jobJPanel.add(jobIdLabel);
        jobJPanel.add(jobIdTextField);
        jobJPanel.add(jobSizeLabel);
        jobJPanel.add(jobSizeTextField);
        jobJPanel.add(okJobButton);

        FFButton.addActionListener(e -> {
    
    
            memory = new Memory(640);
            changeButton.setEnabled(false);
            FFButton.setEnabled(false);
            NFButton.setEnabled(false);
            BFButton.setEnabled(false);
            WFButton.setEnabled(false);
            memory.setStartFlag(model);
            memory.setFlag("FF");
            memory.start();

        });
        NFButton.addActionListener(e -> {
    
    
            memory = new Memory(640);
            changeButton.setEnabled(false);
            FFButton.setEnabled(false);
            NFButton.setEnabled(false);
            BFButton.setEnabled(false);
            WFButton.setEnabled(false);
            memory.setStartFlag(model);
            memory.setFlag("NF");
            memory.start();

        });
        BFButton.addActionListener(e -> {
    
    
            memory = new Memory(640);
            changeButton.setEnabled(false);
            FFButton.setEnabled(false);
            NFButton.setEnabled(false);
            BFButton.setEnabled(false);
            WFButton.setEnabled(false);
            memory.setStartFlag(model);
            memory.setFlag("BF");
            memory.start();

        });
        WFButton.addActionListener(e -> {
    
    
            memory = new Memory(640);
            changeButton.setEnabled(false);
            FFButton.setEnabled(false);
            NFButton.setEnabled(false);
            BFButton.setEnabled(false);
            WFButton.setEnabled(false);
            memory.setStartFlag(model);
            memory.setFlag("WF");
            memory.start();

        });
        changeButton.addActionListener(e -> {
    
    
            if(e.getActionCommand().equals("自动演示")&&!model){
    
    
                changeButton.setText("手动演示");
                nextButton.setEnabled(true);
                model=true;
            }else if(e.getActionCommand().equals("手动演示")&&model) {
    
    
                changeButton.setText("自动演示");
                nextButton.setEnabled(false);
                model=false;
            }

        });
        nextButton.setEnabled(false);
        nextButton.addActionListener(e -> {
    
    
            memory.getLock().lock();
            memory.getCondition().signalAll();
            memory.getLock().unlock();
            nextButton.setEnabled(false);
        });
        buttonJPanel.add(FFButton);
        buttonJPanel.add(NFButton);
        buttonJPanel.add(BFButton);
        buttonJPanel.add(WFButton);

        changeButtonJPanel.add(changeButton);
        changeButtonJPanel.add(nextButton);
        southJPanel.add(jobJPanel);
        southJPanel.add(buttonJPanel);
        southJPanel.add(changeButtonJPanel);
        southBox.add(southJPanel);
        jFrame.add(southBox, BorderLayout.SOUTH);
        jFrame.setVisible(true);
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);


    }

    public void updateUI(){
    
    
            imagePanel.removeAll();
            imagePanel.add(new JLabel(new ImageIcon(memory.drawImage())));
            imagePanel.updateUI();
    }

    public JButton getFFButton() {
    
    
        return FFButton;
    }

    public JButton getNFButton() {
    
    
        return NFButton;
    }

    public JButton getBFButton() {
    
    
        return BFButton;
    }

    public JButton getWFButton() {
    
    
        return WFButton;
    }

    public JButton getChangeButton() {
    
    
        return changeButton;
    }

    public JButton getNextButton() {
    
    
        return nextButton;
    }

    public static void main(String[] args) {
    
    
        getOwm().init();
    }

}

(6)结果
可视化结果展示

猜你喜欢

转载自blog.csdn.net/qq_40100414/article/details/113822960