Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.FileWriter;
- import java.io.IOException;
- import java.io.BufferedReader;
- import java.io.InputStreamReader;
- import java.util.Random;
- import java.lang.String;
- class Operation // операция по заполнению
- {
- int startPosition; // с какой ячейки начали заполнять память
- int size; //сколько памяти заполнили
- int data; //чем заполнили
- int ThreadNum; //какой поток это хотел
- int num; //какой номер (айди) у этого запроса ( он может совпадать у разных потоков)
- Operation(int stPos, int length, int data, int ThreadNum, int num)
- {
- startPosition = stPos;
- this.size = length;
- this.data = data;
- this.ThreadNum = ThreadNum;
- this.num = num;
- }
- // функции - getter`ы
- final int size()
- {
- return size;
- }
- final int ThreadNum()
- {
- return ThreadNum;
- }
- final int data()
- {
- return data;
- }
- final int num()
- {
- return num;
- }
- final int startPosition()
- {
- return startPosition;
- }
- }
- class Request // запрос
- {
- int size;
- int ThreadNum;// вместе номер потока и номер запроса однозначно определяют запрос
- int data;
- int num;//номер запроса
- Request(int size, int ThreadNum, int data,int num)
- {
- this.size = size;;
- this.ThreadNum = ThreadNum;
- this.data = data;
- this.num = num;
- }
- final int size()
- {
- return size;
- }
- final int ThreadNum()
- {
- return ThreadNum;
- }
- final int data()
- {
- return data;
- }
- final int num()
- {
- return num;
- }
- }
- class file // снгл-класс для доступа к файлу остальными классами
- {
- public static FileWriter getInstance()
- {
- if(instance == null)
- instance = new file();
- return os;
- }
- private static FileWriter os;
- private static file instance;
- file()
- {
- try {
- os = new FileWriter("data.txt");
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- class Data
- {
- private int arr[]; //массив с данными (память)
- private Stack <Request> stackOfRequests; //массив запросов
- private Stack <Operation> stackOfOperations; //массив операций
- private static Data instance = new Data();
- boolean isReady = true;
- public static Data getInstance(){ //синглтон
- if(instance == null)
- instance = new Data();
- return instance;
- }
- private Data(){
- stackOfRequests = new Stack<Request>();
- stackOfOperations = new Stack <Operation>();
- arr = new int[5000];
- }
- private int FindPlace(int size){ // получает длинну памяти которая нужна и ищет такой кусок который заполнен нулями
- int j;
- for(int i = 0; i < 5000; i++)
- {
- for( j = i; j < 5000; j++)
- {
- if(arr[j] != 0 || j-i > size)
- break;
- }
- if(j-i > size)
- return i;
- }
- return 0;
- }
- public final boolean isReady(){return isReady;}
- private void Fill(){ // заполняет массив памяти извлекая запросы из стека
- Request req = stackOfRequests.pop(); // извлекает запрос из стека
- int place = FindPlace(req.size()); // ищет индекс места в массиве
- Operation op = new Operation( place, // указаетль на начало памяти которая будет заполнена
- req.size(), //размер памяти котоый будет заполнен
- req.data(), // цифры которыми заполнится память
- req.ThreadNum(),// номер потока чей это был запрос
- req.num()); // номер запроса у этого потока ( для дальнейшей идентификации операции чтобы ее можно было отменить)
- //создается новая операция (отличается от запроса тем что запрос - это пожелание потока на заполнение данными а операция - это конкретно выполненная операция
- stackOfOperations.push(op); //добавляем эту оперцаию (чтобы ее можно было отменить найдя среди других по номеру потока и номеру запроса)
- for(int i = place; i < place+req.size();i++)
- arr[i] = req.data(); //заполняем кусок от ячейки place размером size
- try {
- file.getInstance().write(req.ThreadNum()+ "," + req.size()); //записываем в файл эту оперцию в виде "номер_потока,длина_запроса"
- file.getInstance().write(System.getProperty("line.separator"));
- } catch (IOException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- }
- private void Out()
- {
- for(int i = 0; i < 50; i++)
- {
- try {
- file.getInstance().write(arr[i]+ " ");
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- try {
- file.getInstance().write(System.getProperty("line.separator"));// фигня для записи новой строки
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- synchronized public void GetRequest(Request req){ // получает запрос за заполнение памяти
- isReady = false;
- try {
- wait(); // говорит что занят
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- if(stackOfRequests.push(req) == -1) // если не удалось добавить запрос в стек
- {
- isReady = true;
- return;
- }
- Fill();// если удалось вызывает этот метод
- Out(); // выводим массив в файл
- isReady = true;
- notify(); // сообщает об освобождении
- }
- synchronized public void GetCancel(int ThreadNum, int operationNum){ // фактически смысле в переменной isReady нету - это чисто показуха потому что функция синхронайзед и присутсивуют методы wait() и notify() который говорят потокам другим что в данный момент метод занят а нотифай сообщает что он освободился
- isReady = false;
- try {
- wait();
- } catch (InterruptedException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- Operation op = stackOfOperations.Find(ThreadNum, operationNum);
- if(op == null){
- isReady = true;
- return;
- }
- stackOfOperations.KickLastFind();
- for(int i = op.startPosition(); i < op.startPosition()+op.size; i++)
- arr[i] = 0;
- try {
- file.getInstance().write("Отменяем операцию "+ op.ThreadNum()+","+ op.size());
- file.getInstance().write(System.getProperty("line.separator"));
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- Out();
- isReady = true;
- notify();
- }
- }
- class MyThread extends Thread
- {
- Request arrOfRequests[]; //массив запросов. каждый
- int numOfRequests = 0; //количество запросов
- int toSend = 0; //индекс последнего отправленного запроса ( т.к. новый запрос может создаться, но не отправиться из-за занятости памяти, в таком случае сохранится индекс его и он отправиться as soon as
- MyThread(String threadName)
- {
- super(threadName);
- arrOfRequests = new Request[500];
- start(); //в конструкторе запускаем поток (он запускается при вызове метода старт который вызывает внутри себя метод ран
- }
- public void run()
- {
- //System.out.println("Добавлен поток с номером " + this.getName());
- while(true)
- {
- Random r = new Random(); // обьект для генерирования произв чисел
- int k = r.nextInt()%2; // генерируем или один или ноль
- int name = Integer.parseInt(this.getName());
- if(k == 0 || numOfRequests == 0) // если ноль ( или если запросов еще не было т.к. нету смысла в удалении запроса если его не было) то добавляем новый запрос
- {
- int length = Math.abs(r.nextInt()%10); // генерируем длину для заполнения памяти
- arrOfRequests[numOfRequests] = new Request(length,name, name, numOfRequests);// добавляем в массив запросов этот запрос
- // в конструктор передаем сколько бит надо заполнить, какими числами надо заполнить, какой номер потока котоый хочет это сделать, и под каким номером хранится этот запрос внутри самого потока
- if(Data.getInstance().isReady()) // в случае если память готова
- Data.getInstance().GetRequest(arrOfRequests[toSend++]); // отправляем последний неотправленный запрос (с индексом toSend )
- numOfRequests++;//в любом случае (отправили запрос или нет) увеличиваем счетчик ( а если отпарвили еще и счетчик отправленных запросов toSend
- try {
- sleep(1000*length); //засыпает пропорционально отправленной длинне данных
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- else // в случае же если нуль, то удаляем( отменяем одну из операций )
- {
- int n = r.nextInt()%numOfRequests; // находим произвольно одну из предыдущих операций
- if(arrOfRequests[n] == null) // если она уже была отменена
- continue; // начинаем весь цикл заново
- if(Data.getInstance().isReady()) // если же нет проверяем готовность памяти
- Data.getInstance().GetCancel(name, n); // и посылаем запрос на удаление
- // что важно - здест отсутствует удаление запроса который был только что отменен забыл я это сделать
- }
- }
- }
- }
- class Stack <Type>
- {
- private Type[] mass = (Type[])new Object[50000];;// массив обьектов
- final int SIZE = 500; //масимальный развер
- int num = 0; //текущий индес последнего обьекта
- int first = 0; //при считывании элемента мы не сдвигаем все остальные элементы назад а просто пересохраняем индекс первого элемента
- // (считывается всегда элемент с индексом first а добавляется новый элемент в конец с индексом num
- int lastFind;
- Stack ()
- {
- }
- int push(Type elem)
- {
- if(num + 1 < 500)
- {
- mass[num++] = elem;
- return num;
- }
- else return -1;
- }
- public Type pop()
- {
- if(num > 0)
- return mass[first++];
- throw new ArrayIndexOutOfBoundsException(-1);
- }
- // под операцией подразумевается заполнение определнного куска памяти числами определенным потоком
- Operation Find(int ThreadNum, int numOper){ // для поиска операции получает номер потока и номер запроса-операции в этом потоке
- for(int i = 0; i < num; i++)
- {
- if( ((Operation)mass[i]).ThreadNum() == ThreadNum &&
- ((Operation)mass[i]).num() == numOper)
- {
- lastFind = i;
- return ((Operation)mass[i]);
- }
- }
- return null;
- }
- void KickLastFind(){ // удаляет последний найденный элемент методом Find и сдивгает массив
- for(int i = lastFind ; i < num-1; i++)
- mass[i] = mass[i+1];
- num--;
- }
- }
- public class Chief
- {
- public static void main (String args[])
- {
- BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); // для считывания строки ридер
- MyThread[] threads = new MyThread[500]; //массив потоков
- int numOfThreads = 1; // количество потоков (начиная с единицы чтобы не было потока с нулевым номером
- while(true)
- {
- String str = "";
- try {
- str = in.readLine(); // считываем строку
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- if(str.equals("+")) // если строка равна + то добавляем новый поток
- {
- threads[numOfThreads-1] = new MyThread(Integer.toString(numOfThreads));// добавляем в массив новый поток, передавая в качестве параметра (имени) номер текущего потока в массиве
- numOfThreads++;
- }
- else // если строка не равна плюсу то закрываем файловый поток и завершаем программу (но завершается основной поток только все остальные остаются
- {
- try {
- file.getInstance().close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- break;
- }
- }
- }
- }
Add Comment
Please, Sign In to add comment