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.