Wydaje naprzemienne usypianie wątków

0

Witam

Tworzę wątkowy kod odczytu dużych danych z dysku i przesylania ich przez socket.

Mam dwie klasy (wątki dziedziczą po Thread):

DataHandling - odpowiedzialna za odczyt jakieś części danych pliku do bufora po czym sam wątek się usypia. Budzenie następuje gdy wątek klasy MainSocket pobierze dane zbuforowane do wysyłki przez socket.

MainSocket - odpowiedzialny za wysylke danych i komunikatow-sterowania. Chce aby na czas działania wątku DataHandling do momentu jego uśpienia klasa ta czekała na nowe dane w buforze.

Oto co zrobiłem:

 

public class DataHandling extends Thread {

    private byte[] byteBuffer;
    private int lenghtOfSelectedFile;
    private File selectedFile;
    private int sizeOfByteBuffer;
    private boolean fileReadComplate;
    private String lastError = "";
    
    


    private boolean suspend;
    private boolean dataRead;


    private FileInputStream inputStream;

    public DataHandling(int sizeOfByteBuffer, File selectedFile) {
        super("Watek asynchronicznego odczytu pliku na dysku");
        this.sizeOfByteBuffer = sizeOfByteBuffer;
        this.selectedFile = selectedFile;
    }
  
    public void resumeReading() {
        synchronized (this) {
            suspend = false;
            notify();
        }
    }
 
    public String getLastError() {
        return lastError;
    }

    public boolean isFileReadComplate() {
        return fileReadComplate;
    }

    public boolean isDataRead() {
        return dataRead;
    }

    private void loadFileFromHdd() throws IOException {

        /*tutaj kod odpowiedzialny za czytanie do buffora*/

        if (inputStream.available() >= sizeOfByteBuffer) {
            byteBuffer = new byte[sizeOfByteBuffer];
        } else {
            byteBuffer = new byte[inputStream.available()];
        }        
        
        int liczbaOdczytanychBajtow = inputStream.read(byteBuffer);
        
        if (liczbaOdczytanychBajtow > 0) {
            dataRead = true;
            suspend = true;
        } else {
            fileReadComplate = true;                        
            inputStream.close();

        }        

    }

    @Override
    public void run() {
        try {
            while (!fileReadComplate) {
                dataRead =false;
                loadFileFromHdd();
                synchronized (this) {
                    while (suspend) {                 
                        wait();
                    }
                }                
            }            

        } catch (Exception e) {
            lastError = "Blad w czytaniu pliku z dysku: " + e.getMessage();
        }
    }
}
public class MainSocket extends Thread {

private DataHandling dataHandling;

/*tu inne rzeczy i metody*/

@Override
    public void run() {
 dataHandling.start();
.
.
.
                while (!dataHandling.isFileReadComplate()) {
                    while (!dataHandling.isDataRead()) {

			TUTAJ!
			Jak wydajnie stopować/waitować tą prawie pustą pętle (wychodzi dopiero z niej gdy watęk dataHandling da znać że zapełnił buffor

                        if (!dataHandling.getLastError().isEmpty()) {
                            throw new Exception(dataHandling.getLastError());
                        }
                        if (dataHandling.getState().equals(dataHandling.getState().TERMINATED) && !dataHandling.isFileReadComplate()) {
                            throw new Exception("Watek odczytu pliku zakonczony, a odczyt niepelny");
                        }
                        if (dataHandling.isFileReadComplate()) {
                            break;
                        }
                    }
                    byte[] pobranyBuffor = dataHandling.getByteBuffer();
                    dataHandling.resumeReading();
			/* tutaj metoda ktory jest odpowiedzialna za słanie przez socket*?

                }

Ta prawie pusta pętla bierze bardzo dużo czasu pracy. Przejściowym rozwiązaniem jest danie po prostu Thread.sleep(100) (zwiększa efektywność - krótszy czas wykonania) w niej, ale czy nie ma bardziej profesjonalnego sposobu?

Gdyby wątek dataHandling w całości kończył swą czynnosc a nie popadał w uspienie to użyłbym join'a - ale jak widac nie moge.

0

Po pierwsze szkielet Executor i niech on zarządza wątkami.
Po drugie coś co się Callback nazywa i pozwala na powiadamianie innych wątków: http://stackoverflow.com/questions/826212/java-executors-how-to-be-notified-without-blocking-when-a-task-completes

1 użytkowników online, w tym zalogowanych: 0, gości: 1