Java多執行緒經典題目(醫院挂號)

  • 2020 年 11 月 15 日
  • 筆記

題目

實現一個醫院的挂號機系統,要求:有多台挂號機同時運行,此時無論有多少患者挂號,要求都能掛到不同
的號碼,並且要求實現當意外斷電之後,下一次恢復還能從上次結束號碼繼續挂號?
* synchronized
* 文件操作
* IO流

解題思路

此題的難點在於這個斷電,首先java處理斷電續傳等問題,一般我們使用RandomAccessFile這個流,因為它裡面
有個seek方法,可以設置游標的偏移量,可以從超大的文本中快速定位我們的游標。所以我們可以將已經掛的號存
到一個新文件,然後每個執行緒執行挂號的時候都讀取新文件的length長度作為seet的偏移量,以此來達到斷電之後
也能從上次結束號碼繼續挂號。

源程式碼如下:

package com.thospital;

/**
 * User:zhang
 * Date:2020/11/10
 **/

import java.io.*;


public class TestHospital {
    public static void putNum(File file) {
        try {
            DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
            for (int i = 1; i < 10001; i++) {
                dos.writeInt(i);
            }
            dos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        try {
            RandomAccessFile r=new RandomAccessFile("d:\\a.txt","r");
//            下面不能用randomAccessFile,因為它是覆蓋寫,並且到達上次長度才能改變它的長度
            DataOutputStream w = new DataOutputStream(new FileOutputStream("d:\\b.txt",true));
            IOThread ioThread = new IOThread(r,w);
            Thread thread1 = new Thread(ioThread, "挂號機一號");
            Thread thread2 = new Thread(ioThread, "挂號機二號");
            Thread thread3 = new Thread(ioThread, "挂號機三號");
            Thread thread4 = new Thread(ioThread, "挂號機四號");
            thread1.start();
            thread2.start();
            thread3.start();
            thread4.start();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class IOThread implements Runnable {
    private RandomAccessFile ra=null;
    private DataOutputStream wr=null;
    private File file=new File("d:\\b.txt");
    public IOThread(RandomAccessFile r, DataOutputStream w) {
        this.ra = r;
        this.wr = w;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        while (true){
        System.out.println("患者在" + name + "掛到了" + getNum() + "號");
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


    }

    public synchronized int getNum() {
        try {
            Thread.sleep(1000);
//            判斷文件的長度就用文件的length
            ra.seek(file.length());
            int i = ra.readInt();
            wr.writeInt(i);
            if (i != -1) {
                return i;
            }else {
                return -1;
            }

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return 0;
    }
}


```java