Ringpuffer(ein und auslesen von daten)

Hallo,

also die Aufgabe ist es 3 verschiedene Werte von einer Hardware zu holen, diese dann alle 500ms von der HW in den Ringpuffer schreiben und halt auszulesen und Grafisch nach der Zeit darzustellen(y-Achse: Werte und x-Achse: Zeit). Also 3 Graphen sind es insgesamt.

Das ganze wurd jetzt mit einem Timer-Event realisiert, die werde wurden also einfach immer eingelesen und gezeichnet, wenn es einen Timer_interrupt gab, aber nun muss das ganze mit Ringpuffer realisiert werden(Graphen zeichen und Werte einlesen hat ja schon geklappt mit Timer).

Hier mein Ansatz:

class Write_Task implements Runnable {
		Thread thread;

		public Task1() {
			thread = new Thread(this);
		}

		  public void run() {
			int anz;
			Daten[] src;
			//hier irgendwie die Daten auslesen, aber wie ist die Frage
			
			System.out.println("Task 1 gestartet!");
			anz = rbf.write(src, 1);
			while (anz < 1) {
				anz += rbf.write(src, 1);
			}
			System.out.println("anz = " +anz);
			try {
				thread.sleep(500); // Erfassung alle 500 ms
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	

	class Read_Task implements Runnable {
		Thread thread;

		public Task2() {
			thread = new Thread(this);
		}

		public void run() {
			int anz;
			Daten[] dest = new Daten[10];

			System.out.println("Task 2 gestartet!");

			do {
				anz = rbf.read(dest, 1);
				
			} while (anz > 0);
		}
	}
}

Die Klasse “Daten” ist selbsterstellt und darin befinden sich die 3 get-Methoden, die 3 Werte von der Hardware holen. Naja eig. ist der Ringpuffer ja umsonst, da man nur Wert für wert rein schreibt und dann halt wert für wert liest. Aber egal, die Aufgabenstellung will es halt so.

Mir ist aber noch nicht so klar, was nun dieses Klassen-Array Daten bezwecken soll. In einem normalen Integer Array stehen doch Integer-Werte darin, aber was hilfst das Array Daten hier weiter? Was steht da in einem Feld? Objekte bzw. Instanzen von der Klasse Daten?

Also hätte wer einen Tipp, wie ich das so machen könnte? Also alle 3 Werte irgendwie in so ein “klassen-array” speichern und dann in den Ringpuffer schreiben, um in dann leicht wieder lesen zu können, sodass kein durcheinander der Werte kommt.

Danke!

mfg

Klingt etwas konfus. Gibt’s da eine richtige Aufgabenstellung dazu? Was ist “rbf” (Glaskugel: “RingBuFfer”? Wenn nicht: Ich kaufe ein “i” :D). Hast DU die Klasse “Daten” erstellt? …

Naja, ich hab ja von dem Thread-Zeugs keinen wirklichen Plan, aber ich denk mal…
Es sollte wohl Minimum 2 Threads geben. Der eine kümmert sich alle x Sekunden darum, Torten (Daten) auf ein Förderband (Ringbuffer) zu schaufeln und der andere Thread nimmt sie von dort weg,
wenn er Zeit hat und es etwas abzuholen gibt und verziert sie dann. Werden die Torten nicht vom Verzier-Thread abgeholt, fallen sie vom Förderband hinten wieder runter.
Das Beladen des Förderbandes mit Torten hätte Priorität vor dem Verzieren, z.B. weil die Torten sonst den Ofen blockieren würden… owehoweh…
Schön wär es wahrscheinlich aber schon, wenn die Torten vom Förderband genommen werden könnten, bevor die Daten äh. Torten hinten wieder runter krachen.

Ja, die Klassen Daten ist selbst erstellt und da sind ja wie gesagt die ganzen get-Mothden drinnen die, die 3 verschiedenen Werte holen(Temperatur, Poti und Sinus).

Aufgabe:
-Erfassungs-Thread erfasst alle 500ms Wert von PIC-Dem_FS_USB, versieht Wert mit einer Zeitmarke (simuliert Erfassungsintervall 30sek.) und schreibt diesen Wert in Ringpuffer
-Anzeige-Thread liest Werte aus Ringpuffer und gibt Wert in Diagramm (jFreeChart) aus - Zeitmarke ist x-Koordinate!!
-ev. implementiert man den Ringpuffer als generische Klasse (für Verwendung mit Klasse “Messwert”

Du kannst dem Write_Task einfach alle benötigten Informationen über den Konstruktor mitteilen.

new Write_Task (daten);

Geheimtipp: java.nio.ByteBuffer…
In dem Thread, der die Hardware ausliesst erstellst du ein ByteArray entsprechend der Länge der gelesenen Werte und wrapst dieses in einen ByteBuffer. ByteArray und -Buffer werden in diesem Thread beide als Membervariablen benötigt, das Array zur synchronisation des Schreibzugriffs und der Buffer zum konfortablen Schreiben der Werte. Um das ByteArray nach aussen hin lesbar zu machen, genügt dann ein “return dataBuffer.duplicate().asReadOnlyBuffer();”, wobei man aber noch die Indexpointer und Datentypen zum Lesen der einzelnen Werte benötigt. Von daher empfiehlt sich noch eine entsprechende Kapselung des Buffers in eine Klasse mit entsprechenden Gettern.
Je nach Datentyp geht das mit spezifischeren Buffern sogar noch etwas leichter.

import java.nio.DoubleBuffer;

public final class RingBuffer {
	private byte[] arrayBuffer;
	private HardwareBuffer hwEmm, hwTask;
	private DoubleBuffer dataBuffer;
	private Thread hwReader;

	public RingBuffer() {
		arrayBuffer = new byte[3 * 8];
		dataBuffer = ByteBuffer.wrap(arrayBuffer).asDoubleBuffer();
		hwEmm = new HW_Emulator();
		hwTask = new HardwareBuffer() {
			@Override
			public double getTemperature() {
				return dataBuffer.get(0);
			}
			
			@Override
			public double getSinus() {
				return dataBuffer.get(1);
			}
			
			@Override
			public double getPoti() {
				return dataBuffer.get(2);
			}
		};
		hwReader = new Thread() {
			@Override
			public void run() {
				while(!isInterrupted()) {
					synchronized (arrayBuffer) {
						dataBuffer.put(0, hwEmm.getTemperature());
						dataBuffer.put(1, hwEmm.getPoti());
						dataBuffer.put(2, hwEmm.getSinus());
					}
					try {
						Thread.sleep(500);
					} catch(InterruptedException e) {
						interrupt();
					}
				}
			}
		};
		hwReader.start();
	}

	public HardwareBuffer getHardwareBuffer() {
		if(hwReader == null) {
			throw new IllegalStateException("RingBuffer destroyed");
		}
		return hwTask;
	}

	public void destroy() {
		hwReader.interrupt();
		hwReader = null;
		hwEmm = hwTask = null;
		dataBuffer = null;
		arrayBuffer = null;
	}
}

interface HardwareBuffer {
	double getTemperature();
	double getPoti();
	double getSinus();
}

class HW_Emulator implements HardwareBuffer {
	@Override
	public double getTemperature() {
		return Math.random();
	}
	@Override
	public double getPoti() {
		return Math.random();
	}
	@Override
	public double getSinus() {
		return Math.random();
	}
}```Für einen grösseren Ringbuffer muss man nun nichts weiter tun, als das ByteArray entsprechend zu vergrössern und einen Index pro Datenerfassung um die Anzahl der erfassten Daten zu erhöhen.

Danke,aber wie meinst du das? Die Frage ist doch was genau ein Klassenarray ist. Schaut doch mal Zeile 11 bitte. Da erstelle ich ja so ein Klassenarray, aber wie funktioniert das?
Oder funktionieret das überhaupt mit einem Klassenarray?

Naja ich lese außerdem ja nur Zeichen für zeichen ein und das halt alle 500ms, d.h. ich schreibe nicht zuerst den Buffer voll und lese dann alles raus. SONDERN: ich schreib zeichen in den buffer und es wird auch sofort gelesen.

Ein normales Integer array, hat doch integer felder, wo auf einem feld eine integer variable steht. Aber wie ist es bei einem Array mit Typ Daten.

Wichtig: Daten ist eine von mir selbst erstellte klasse, ich kann mittels src.getWert1(), src.getWert2() und srcgetWert3()(bei: Daten[] scr = new Daten[10]) auf die Werte zugreifen. Versteht ihr mein Problem und was ich meine?

Das Prinzip eines Ringpuffers ist bekannt? http://de.wikipedia.org/wiki/Warteschlange_(Datenstruktur)#Implementierung_als_Ringpuffer

Ein Array ist ein Behälter das eine feste Anzahl an Objekten/Primitiven eines bestimmten Datentyps aufnehmen kann. Wäre also geeignet um damit einen Ringpuffer für bezu implementieren.

Ich verstehe es nicht. Entweder fehlt da was im Satz oder die Aussage ist falsch wenn src Dein Array ist das Datenobjekte enthält, dann geht kein src.getWert... Falls gefüllt ginge src[0].getWert1();

Hab mal einen Generischen Ringbuffer geschrieben, vielleicht fängst du ja was damit an:


/**
 * This class is an implementation of a generic ring buffer.
 * 
 * @author bERt0r
 * 
 */
public class RingBuffer<T>
{
	private Object[] buffer;
	private int position, limit;
	
	/**
	 * Creates a new RingBuffer with the specified size. Size has to be bigger
	 * than 0.
	 * 
	 * @param size
	 *            the size of the buffer
	 */
	public RingBuffer(int size)
	{
		if (size < 1)
		{
			throw new IllegalArgumentException("Size hast to be bigger than 0");
		} else
		{
			buffer = new Object[size];
			limit = size;
		}
	}
	
	/**
	 * Writes an element to the current position of the ringbuffer and then
	 * increments the position. If the limit of the buffer is reached, the
	 * position is reset to 0 before writing the element.
	 * 
	 * @param element
	 *            the element to write into the buffer.
	 */
	public void put(T element)
	{
		if (position >= limit)
		{
			position = 0;
		}
		buffer[position] = element;
		position++;
	}
	
	/**
	 * Absolute get method. Reads the object at the given index.
	 * 
	 * @param index
	 *            The index from which the object will be read.
	 * @return The Object at the given index.
	 */
	@SuppressWarnings("unchecked")
	public T get(int index)
	{
		return (T) buffer[index];
	}
	
	/**
	 * Returns this buffers position.
	 * 
	 * @return The position of this buffer.
	 */
	public int position()
	{
		return position;
	}
	
	/**
	 * Sets this buffers position
	 * 
	 * @param position
	 *            The new position value; must be non-negative and no larger
	 *            than the current limit
	 * @throws IllegalArgumentException
	 *             - If the preconditions on newPosition do not hold
	 */
	public void position(int position)
	{
		if (position < 0 || position >= limit)
		{
			throw new IllegalArgumentException("Position < 0 or > limit");
		}
		this.position = position;
	}
	
	/**
	 * Returns this buffers limit.
	 * 
	 * @return The limit of this buffer.
	 */
	public int limit()
	{
		return limit;
	}
	
	/**
	 * Sets this buffer's limit.
	 * 
	 * @param limit
	 *            The new limit value; must be non-negative and no larger than
	 *            this buffer's capacity
	 * @throws IllegalArgumentException
	 *             - If the preconditions on newLimit do not hold
	 */
	public void limit(int limit)
	{
		if (limit < 1 || limit > buffer.length)
		{
			throw new IllegalArgumentException("Limit < 1 or > Capacity (" + buffer.length + ")");
		}
		this.limit = limit;
	}
	
	@SuppressWarnings("unchecked")
	public T[] toArray()
	{
		return (T[]) buffer;
	}
	
	/**
	 * Returns this buffers capacity.
	 * 
	 * @return The capacity of this buffer.
	 */
	public int capacity()
	{
		return buffer.length;
	}
	
	/**
	 * Convenience Method to write an array of objects into this buffer at the
	 * current position.
	 * 
	 * @param arr
	 *            The array to be written into this buffer.
	 * @param offset
	 *            The offset within the array of the first object to be read;
	 *            must be non-negative and no larger than array.length
	 * @param length
	 *            The number of objects to be read from the given array; must be
	 *            non-negative and no larger than array.length - offset
	 */
	public void put(T[] arr, int offset, int length)
	{
		int bound = offset + length;
		for (int i = offset; i < bound; i++)
		{
			put(arr**);
		}
	}
	
	/**
	 * Resizes this buffer to the given size.
	 * @param size The new size of this buffer.
	 */
	public void resize(int size)
	{
		T[] help=toArray();
		int cur=position;
		position=0;
		limit=size;
		buffer=new Object[size];
		put(help,cur,help.length-cur);
		put(help,0,cur);
	}
	
}

Danke!

Ja, mir ist klar wie ein Ringpuffer funktioniert, doch der Lehrer will es so, wie sein der Aufgabe beschrieben wird bzw. halt so mit dem Ringpuffer(zeichen für zeichen).

Zum Klassenarray:
Alle 500ms wird doch in den Ringpuffer geschrieben bzw. so muss ich das machen. Aber ich hab doch 3 Werte. Wie soll ich das realisieren? Kann an src[0] alle 3 Werte(wert1,wert2,wert3) stehen? Nein oder? Ich verstehe noch nicht so ganz was dieses Klassenarray bezwecken soll.

Ich muss doch auch die Werte dauernd auslesen. Kann ich nicht die 3 verschiedenen Werte in ein Gesamtpaket(also z.b. auf src[0]) verfrachten, dies dann in den Buffer schreiben und anschließend das Paket lesen und 3 Graphen daraus machen?

Ich glaube ich bin noch ein bisschen verwirrt. Bitte erklärt mir das.

PS: Ja rbf ist das erstellte Objekt der Ringpuffer-Klasse

public class Ringpuffer {
	private Datenbuf[];
	private int bufsize;
	private int next_read;
	private int cnt;
	
	public Ringpuffer (int size) {
		bufsize = size;
		buf = new Daten[bufsize];
		next_read = 0;
		cnt = 0;
	}
	
	public synchronized int write (Daten[] src, int num) {
		int geschrieben = 0;
		
		while((geschrieben < num) && (cnt < bufsize)) {
			buf[(next_read+cnt)%bufsize] = src[geschrieben];
			++geschrieben;
			++cnt;
		}	
		
		return geschrieben;
	}
	
	public synchronized int read (Daten[] dest, int num) {
		int gelesen = 0;
		
		while((gelesen < num) && (cnt > 0)) {
			dest[gelesen] = buf[next_read];
			++gelesen;
			--cnt;
			next_read = (next_read+1)%bufsize;
		}
		
		return gelesen;
	}
	
}

vielleicht hilft auch das
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ArrayBlockingQueue.html
mit dem

Alle 500 Millisekunden kommen 3 Werte in den Ringpuffer? Dann erstellst du dir entweder eine Klasse mit den 3 Werten und packst jedes mal ein Objekt dieser Klasse in den Puffer. Alternativ geht auch einfach ein Array[3].

Hier ist mal ein vollständiger Ringbuffer:

import java.nio.DoubleBuffer;

public final class RingBuffer {
	private byte[] arrayBuffer;
	private HardwareBuffer hwEmm, hwTask;
	private DoubleBuffer dataBuffer;
	private Thread hwReader;
	private final int size;
	private int cnt;

	public RingBuffer(long timer) {
		size = (int) ((timer + 499) / 500);
		if(size <= 0) {
			throw new IllegalArgumentException("invalid value " + timer);
		}
		arrayBuffer = new byte[3 * 8 * size];
		dataBuffer = ByteBuffer.wrap(arrayBuffer).asDoubleBuffer();
		hwEmm = new HW_Emulator();
		hwTask = new HardwareBuffer() {
			@Override
			public double getTemperature(int index) {
				return dataBuffer.get(index + 0);
			}
			
			@Override
			public double getSinus(int index) {
				return dataBuffer.get(index + 1);
			}
			
			@Override
			public double getPoti(int index) {
				return dataBuffer.get(index + 2);
			}
		};
		hwReader = new Thread() {
			@Override
			public void run() {
				while(!isInterrupted()) {
					synchronized (arrayBuffer) {
						dataBuffer.put(cnt + 0, hwEmm.getTemperature(0));
						dataBuffer.put(cnt + 1, hwEmm.getPoti(0));
						dataBuffer.put(cnt + 2, hwEmm.getSinus(0));
					}
					cnt += 3;
					cnt /= size;
					try {
						Thread.sleep(500);
					} catch(InterruptedException e) {
						interrupt();
					}
				}
			}
		};
		hwReader.start();
	}

	public int getBufferSize() {
		return size;
	}

	public HardwareBuffer getHardwareBuffer() {
		if(hwReader == null) {
			throw new IllegalStateException("RingBuffer destroyed");
		}
		return hwTask;
	}

	public void destroy() {
		hwReader.interrupt();
		hwReader = null;
		hwEmm = hwTask = null;
		dataBuffer = null;
		arrayBuffer = null;
	}
}

interface HardwareBuffer {
	double getTemperature(int index);
	double getPoti(int index);
	double getSinus(int index);
}

class HW_Emulator implements HardwareBuffer {
	@Override
	public double getTemperature(int index) {
		return Math.random();
	}
	@Override
	public double getPoti(int index) {
		return Math.random();
	}
	@Override
	public double getSinus(int index) {
		return Math.random();
	}
}```Diesen kann man nun zyklisch oder on demand in einer Schleife auslesen und die Werte in die Puffer der JFX_ChartViews schreiben.
```HardwareBuffer bf = myRingBuffer.getHardwareBuffer();
int s = myRingBuffer.getSize();
for(int n = 0; n < s; n++) {
  tempChartBuffer.put(n, bf.getTemperature(n));
  potiChartBuffer.put(n, bf.getPoti(n));
  sinusChartBuffer.put(n, bf.getSinus(n));
}```Der Sinn eines Ringbuffers liegt ja afaik darin, dass er eine feste Größe und Struktur hat, so dass ständige Objektinitialisierungen (new) zur Laufzeit ausbleiben können.

funktioniert, wie ich mir das vorstell, aber ob das so ok ist, keine Ahnung.
Mit Threads hab ich noch kaum was gemacht.

import java.util.TimerTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;


public class FiFoTest {

    public static void main(String[] args) throws Exception {
        BlockingQueue<Double> queue = new ArrayBlockingQueue<Double>(3);
        Timer timer = new Timer();
        Write_Task producer = new Write_Task(queue);
        Read_Task consumer = new Read_Task(queue);
        timer.scheduleAtFixedRate(new Task(producer,consumer), 500, 500);
        Thread.sleep(10000);
        timer.cancel();
    }
}

class Task extends TimerTask
{
  protected Write_Task producer = null;
  protected Read_Task consumer = null;
  public Task(Write_Task producer,Read_Task consumer) {
      this.producer = producer;
      this.consumer = consumer;
  }
  @Override public void run()
  {
      new Thread(producer).start();
      new Thread(consumer).start();
      System.out.println( "Timertask" );
  }
}

class Write_Task implements Runnable {

    protected BlockingQueue<Double> queue = null;

    public Write_Task(BlockingQueue<Double> queue) {
        this.queue = queue;
    }

    public void run() {
    	// hier muss halt das Daten-Dingens rein, denk ich.
    	double[] src= new double[3];
    	for (int i = 0; i < src.length; i++) {
			src**=Math.random()*10;
		}
        try {
        	for (int i=0; i < src.length; i++){
                queue.put(src**);        		
        	}
            System.out.println( "Write_Task" );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}



class Read_Task implements Runnable {

    protected BlockingQueue<Double> queue = null;

    public Read_Task(BlockingQueue<Double> queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            System.out.println(queue.take());
            System.out.println(queue.take());
            System.out.println(queue.take());
            System.out.println( "Read_Task" );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Ihr postet leider einen anderen Code, ich soll das ja so fertig machen wie es angefangen wurde. Und dabei brauche ich hilfe.

Hm was meinst du mit Array[3]. Gibt es denn keine Möglichkeit an einer Stelle von einem Array 3 verschiededn Werte zu speichern?(sin, pot, temp.)

Ja, viele gut gemeinte Antworte, die mit der Frage aber vermutlich nicht zuletzt deswegen nicht viel zu tun haben, weil die Frage nicht entsprechend genau gestellt wurde.

Vielleicht mal ganz oben angefangen:

[QUOTE=hallohallo222]Danke,aber wie meinst du das? Die Frage ist doch was genau ein Klassenarray ist. Schaut doch mal Zeile 11 bitte. Da erstelle ich ja so ein Klassenarray, aber wie funktioniert das?
Oder funktionieret das überhaupt mit einem Klassenarray?

Ein normales Integer array, hat doch integer felder, wo auf einem feld eine integer variable steht. Aber wie ist es bei einem Array mit Typ Daten.

Wichtig: Daten ist eine von mir selbst erstellte klasse, ich kann mittels src.getWert1(), src.getWert2() und srcgetWert3()(bei: Daten[] scr = new Daten[10]) auf die Werte zugreifen. Versteht ihr mein Problem und was ich meine?[/QUOTE]

Wenn man einen int[]-Array erstellt, dann kann man damit wie bekannt rumhantieren:

int array[] = new int[10];

array[3] = 12345; // Schreibe einen Eintrag
int intAusDemArray = array[3]; // Lese einen Eintrag

Das ist bei dem “Klassenarray”, wie du es nennst, im Prinzip genauso. Da ist jeder Eintrag des Arrays ein Objekt der entsprechenden Klasse.

Daten array[] = new Daten[10];

array[3] = new Daten(temperatur, poti, sinus); // Schreibe einen Eintrag
Daten datenAusDemArray = array[3];

Wichtig: Solange man keinen Wert an einer Stelle des Array geschrieben hat, ist der Wert, der dort steht, ‘null’ !

Wenn diese Klasse “Daten” (von der wir immernoch nicht wissen, wie sie aussieht!) nun Methoden hat, wie “getTemperatur()” oder so, dann kann man sich ein Objekt aus dem Array holen, und damit dann ganz normal rumhantieren:

Daten array[] = new Daten[10];
array[3] = new Daten(temperatur, poti, sinus);

Daten datenAusDemArray = array[3];
float t = datenAusDemArray.getTemperatur();
...

Man kann auch direkt auf den Arrayeinträgen arbeiten:

Daten array[] = new Daten[10];
array[3] = new Daten(temperatur, poti, sinus);

float t = array[3].getTemperatur();
...

Aber … FALLS das deine Fragen beantwortet, solltest du ggf. mal http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html oder http://openbook.galileocomputing.de/javainsel9/javainsel_03_007.htm#mj11a4689950bdbe50e0c6342eb22737a6 lesen.

also nee… ich hab immerhin „Read_Task“ und „Write_Task“, aber meinen Code schaut offenbar keiner an.
Ich hätte ja gern gewusst, was daran auszusetzen wäre… und das ist KSKB.
Andererseits… war hier irgendwo schon dein „kompletter“ Code oder ein KSKB das ich übersehen hab ??? :suspect:
Ich blick hier langsam die Diskussion nicht mehr…was ist jetzt mit Array… ich denk es soll um sowas wie nen Ringbuffer gehen…:sick:
und freilich kann man andere Klassen in ein Array schreiben, wenn man den Typ vom Array richtig wählt.
Auch BlockingQueue kann man natürlich mit BlockingQueue queue = new ArrayBlockingQueue(3); deklarieren.
Das setzt halt ne Klasse Daten voraus, die ich nicht habe. Soll ich mir eine aus den Fingern lutschen, wozu???
Vielleicht sollt ich mich mal raushalten , oder ???

Ist zwar immernoch anderer Code, aber immerhin schon mal mit DatenArrays:

	private DataObject[] dataBuffer;
	private Data hwEmm;
	private Thread hwReader;
	private int writeCount;

	public RingBuffer(long timer) {
		int size = (int) ((timer + 499) / 500);
		if(size <= 0) {
			throw new IllegalArgumentException("invalid value " + timer);
		}
		dataBuffer = new DataObject[size];
		for(int n = 0; n < dataBuffer.length; n++) {
			dataBuffer[n] = new DataObject();
		}
		hwReader = new Thread() {
			@Override
			public void run() {
				while(!isInterrupted()) {
					dataBuffer[writeCount].temp = hwEmm.getTemperature();
					dataBuffer[writeCount].poti = hwEmm.getPoti();
					dataBuffer[writeCount].sine = hwEmm.getSinus();
					writeCount++;
					writeCount %= dataBuffer.length;
					try {
						Thread.sleep(timeOut);
					} catch(InterruptedException e) {
						interrupt();
					}
				}
			}
		};
		hwReader.start();
	}

	public int getBufferSize() {
		if(hwReader == null) {
			return -1;
		}
		return dataBuffer.length;
	}

	public Data[] getData(Data[] target) {
		if(hwReader == null) {
			throw new IllegalStateException("ringbuffer destroyed");
		}
		if(target == null || target.length < dataBuffer.length) {
			target = new Data[dataBuffer.length];
		}
		for(int n = 0; n < dataBuffer.length; n++) {
			target[n] = dataBuffer[n];
		}
		return target;
	}

	public void destroy() {
		hwReader.interrupt();
		hwReader = null;
		hwEmm = null;
		dataBuffer = null;
	}

	private static class DataObject implements Data {
		private double temp, poti, sine;

		@Override
		public double getTemperature() {
			return temp;
		}

		@Override
		public double getPoti() {
			return poti;
		}

		@Override
		public double getSinus() {
			return sine;
		}
	}
}

interface Data {
	double getTemperature();
	double getPoti();
	double getSinus();
}

class HW_Emulator implements Data {
	@Override
	public double getTemperature() {
		return Math.random();
	}
	@Override
	public double getPoti() {
		return Math.random();
	}
	@Override
	public double getSinus() {
		return Math.random();
	}
}```Das Entscheidende ist, dass der Ringbuffer unabhängig vom Lesetask beschrieben werden kann und dass der Lesetask die interne Datenstruktur auch nicht ändern kann. Die Datenstruktur wird von daher im Konstruktor aufgebaut und zyklisch von einem internen Thread beschrieben. Zum Auslesen der Daten genügt dann zu jeder Zeit ein "getData()", welches stets den kompletten Ringbuffer kopiert und zurück gibt. Damit das LeseArray nicht dauernd neu erstellt werden muss (schadet der Performance), kann man sich hier dem ObjectReuse bedienen. Das LeseArray kann man zwar extern immernoch manipulieren, nur hat man da nicht viel von, weil man an einer Kopie rumwerkelt. Es ist auch völlig egal, zu welchen Zeitpunkt der Buffer ausgelesen wird, oder an welcher Stelle grad' geschrieben wird, Der Puffer wird sich erst im vorgegebenen Zeitraum wieder überschreiben. Wenn er beim ersten Durchgang noch nicht voll ist, seis drum, dann sind die Daten dort halt 0. Ein entsprechender Lesetask könnte dann so aussehen:
```class ReadTask extends Thread {
	@Override
	public void run() {
		long timeOut = 30000;
		RingBuffer rb = new RingBuffer(timeOut);
		Data[] readData = null;
		while(!isInterrupted()) {
			readData = rb.getData(readData);
			// weitere Verarbeitung
			try {
				Thread.sleep(timeOut);
			} catch(InterruptedException e) {
				interrupt();
			}
		}
	}
}```

Semi-OT: @Spacerat :

    Thread.sleep(timeOut);
} catch(InterruptedException e) {
    interrupt();
}```
Warum verwendest du nicht
```try {
    Thread.sleep(timeOut);
} catch(InterruptedException e) {
    Thread.currentThread().interrupt();
}```?

ich würde eher fragen warum gewohnheitsmäßig Thread.sleep() obwohl auf alles andere dank extends Thread direkt zugegriffen wird
man könnte also eher fragen : warum Thread.sleep() statt nur sleep() ?