Контролировать количество потоков, читающих файл в java (только с использованием synchronized, wait, notify и sleep)

В проблеме, которую я пытаюсь решить, каждый поток должен прочитать весь файл (возможно, каждый поток будет доставлять свое содержимое другой задаче или любой другой цели). После его чтения поток должен немного засыпать, а затем попытаться прочитать файл снова, и только заданное количество (n) потоков должно читать файл. Моя попытка решить эту проблему с контролем количества работающих потоков приведена в приведенном ниже коде:

import java.util.*;

class Reader implements Runnable{

Thread t;
Controler c; 

public Reader(Controler c){
    t = new Thread(this);
    this.c = c;
    t.start();
}


public void run(){
    Random ran = new Random();
    int napTime;

    while(true){
        try{

            w.intentarLeerArchivo(t);
            //Specification says that each reader
            //should wait a bit before trying to 
            //read the file again
            napTime = ran.nextInt(1000);
            t.sleep(napTime);
        }catch(InterruptedException e){
            System.out.println("InterruptedException");
        }


    }       
}
}

class Controler{
Random ran;
LinkedList <Reader> readers;

int n; 
int count; 

public Controler(int n){
    readers = new LinkedList <Reader>();
    this.n = n;
    count = 0;
    ran = new Random();

}

public synchronized void getPermission(){
    try{
        while(count >= n){
            wait(); 
        }   
        notify();
    }catch(InterruptedException e){
        System.out.println("InterruptedException");
    }   
}

public synchronized void increaseCount(){
    count++;
}

public synchronized void decreaseCount(){
    count--;
    System.out.println("There are " + count + " threads reading");
}


public void intentarLeerArchivo(Thread t){

    int readTime = 1000;
    try{
        getPermission();

        System.out.println("Thread " + t.getId() +" empezó a leer");
        increaseCount();
        t.sleep(readTime);

        System.out.println("Thread " + t.getId() +" is reading");

        System.out.println("Thread " + t.getId() + " finished reading");            
        decreaseCount();

    } catch(InterruptedException e){
        System.out.println("InterruptedException");
    }
}                       
}



class Initializer{

int numReaders;
int maxReaders;

public Initializer(int numReaders, int maxReaders){
    this.numReaders = numReaders;
    this.maxReaders = maxReaders;
}

public void init(){
    Controler c = new Controler(maxReaders);

    for(int i = 0; i < numReaders; i++){
        new Reader(c);
    }
}


}

public class FileShare{
public static void main(String [] args){
    Initializer c = new Initializer(100, 50);
    c.init();
}

}

Я написал несколько строк для отладки. Они печатают состояние каждого потока и количество потоков, которые читают, когда один из них заканчивает чтение. Но когда я запускаю программу, оказывается, что внезапно появляется больше потоков, читающих файл, чем предполагалось. Я предполагаю, что это как-то связано с моими манипуляциями с синхронизацией. Что я делаю неправильно?

Это может быть проблема X / Y / изобретение колеса заново. Java уже содержит класс, который отслеживает изменения в каталоге (включая его файлы). Рассмотрите возможность использования этого класса вместо того, чтобы пытаться реализовать свой собственный. docs.oracle.com/javase/tutorial/essential/io/notification.ht‌ ml

markspace 07.04.2018 02:13

Я бы так и поступил, но меня попросили заново изобрести колесо в качестве должности.

José Manuel Madrigal Ramírez 07.04.2018 04:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
36
1

Ответы 1

Когда поток находится в

while(...){wait()} 

раздел вашей реализации, он ждет, пока кто-нибудь не уведомит его, чтобы продолжить. Прямо сейчас, когда вы заканчиваете ждать, вы сразу же уведомляете.

Подумайте об этом, если, войдя в систему, я уведомлю кого-нибудь, что должен прийти, он не будет ждать, пока я закончу, прежде чем войти. Вы хотите использовать уведомление, когда вы оставляете файл.

Спасибо! Вот и все!

José Manuel Madrigal Ramírez 07.04.2018 04:58

Другие вопросы по теме