Permalänk
Medlem

java: trådar och arv

Hej,
jag kodar java till en plattform där sensorer uppdateras ofta (ca 3 ms mellan varje uppdatering).

För att informationen från sensorerna ska läsas av parallellt använder jag trådar. ihopsamligen från sensorerna (4 stycken) vill jag gärna ha tillgänglig i en array (borde bli lättare att hantera då). Arrayen vill jag gärna komma åt från en huvudfil.

Nu kommer problemet:
för att skapa en tråd skriver man ex

class sensorThread extends Thread

där sensorThread är klassnamnet.

Jag vill göra värdet från sensorn tillgängligt utanför klassen. För att bli tillgängligt tror jag att arv kanske är en bra ide, finns det bättre sätt?

problemet är att arv skrivs på samma sätt som trådar:

class sensorThread extends huvudklass

Det borde finnas ett bättre/fungerande sätt, eller?

Permalänk
Medlem

Om jag förstår dig rätt så kan du ju ha en variabel i klassen sensorThread som är public där värdet sparas varje gång. Variabeln kan ju då till exempel vara en lista.

Permalänk
Medlem

Det låter som om du vill ha en static-variabel i din klass. En sak du måste tänka på när du ska manipulera samma medlem från flera trådar är att du måste använda dig av någon slags låsning. Någon som är mer insatt i Java kan säkert förklara detta mer ingående.

Visa signatur

Bra, snabbt, billigt; välj två.

Ljud
PC → ODAC/O2 → Sennheiser HD650/Ultrasone PRO 900/...
PC → S.M.S.L SA300 → Bowers & Wilkins 607

Permalänk
Medlem

Titta på interfacet Runnable http://java.sun.com/javase/6/docs/api/java/lang/Runnable.html

public class SensorRunner extends huvudklass implements Runnable { public void run() { //do stuff every 3rd second } } SensorRunner sensorRunner = new SensorRunner(); Thread sensorThread = new Thread(sensorRunner); sensorThread.start();

Permalänk
Medlem

Använd monitorer för att uppnå detta på ett smidigt sätt, med hjälp med nyckelordet synchronized. Man behöver, precis som Phod säger, använda någon form av lås när data ska kommuniceras mellan trådar.

public class SensorValue { private double v; public synchronized double get() { return v; } public synchronized double set(double v) { this.v = v; } } public class SensorThread extends Thread { private SensorValue sensorValue; public SensorThread(SensorValue sensorValue) { this.sensorValue = sensorValue; } public void run() { while (true) { sensorValue.set( ... ); sleep( ... ); } } } // Sen i main eller liknande SensorValue sensorValue = new SensorValue(); SensorThread sensorThread = new SensorThread(sensorValue); sensorThread.start(); while (true) { System.out.println(sensorValue.get()); sleep( ... ); }

(Det finns även mekanismer som automatiskt säger till "huvudtråden" (den som ska läsa) när ett nytt värde är satt i SensorValue. Läs http://java.sun.com/docs/books/tutorial/essential/concurrency... för mer information.)

Permalänk
Medlem

tack. Det var lite klurigt fram till upptäckten att sensorerna i princip inte har någon fördröjning, då borde det funka bra med en samlad tråd för insamling av sensordata till en gemensam array

Roliga än väntat att ta handen vifta med handen framför och displayen säger: "hand framför" och "tomt framför"

Permalänk
Medlem

Static-variabler verkar väldigt malplacerat och monitorer behövs inte så länge du inte skriver sensor-värdena till samma variabel. Du skriver inget om hur du tänker använda dig av klassen, men en vanlig läsning behöver ingen synkronisering.

Känns som du får bättre semantik genom att låta din klass implementera Runnable.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av johhh
Hej,
jag kodar java till en plattform där sensorer uppdateras ofta (ca 3 ms mellan varje uppdatering).

Det låter som ett roligt projekt. Får man fråga vad det är för plattform och vad för sensorer det är?

Permalänk
Medlem

Ett annat alternativ är att använda Atomic*-klasserna i java.util.concurrent.atomic. Om sensordatan kommer i form av flyttal krävs det lite enkla knep för att lagra informationen i en AtomicInteger (för floats) eller AtomicLong (för double), se kodexemplet nedan. Jag tycker att det skulle vara att föredra framför såväl monitorer som finlir med wait/notify. Om du fortfarande är inne på tanken med ha sensordatan i en array, varför inte en AtomicLongArray?

AtomicLongArray ala = new AtomicLongArray(3); ala.set(0, Double.doubleToLongBits(1.23456)); ala.set(1, Double.doubleToLongBits(2.34567)); ala.set(2, Double.doubleToLongBits(3.45678)); double d0 = Double.longBitsToDouble(ala.get(0)); // d0 = 1.23456 double d1 = Double.longBitsToDouble(ala.get(1)); // d1 = 2.34567 double d2 = Double.longBitsToDouble(ala.get(2)); // d2 = 3.45678

Om jag förstått ditt scenario rätt, kan detta gott och väl räcka? Det känns också som den enklaste formen av trådsäkring man kan göra.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av zappox
Static-variabler verkar väldigt malplacerat och monitorer behövs inte så länge du inte skriver sensor-värdena till samma variabel. Du skriver inget om hur du tänker använda dig av klassen, men en vanlig läsning behöver ingen synkronisering.

Känns som du får bättre semantik genom att låta din klass implementera Runnable.

Med antagandet att värdena är av typen double, så citerar jag "Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications." från http://java.sun.com/docs/books/jls/third_edition/html/memory....

Citat:

Ursprungligen inskrivet av badboll
Ett annat alternativ är att använda Atomic*-klasserna i java.util.concurrent.atomic. Om sensordatan kommer i form av flyttal krävs det lite enkla knep för att lagra informationen i en AtomicInteger (för floats) eller AtomicLong (för double), se kodexemplet nedan. Jag tycker att det skulle vara att föredra framför såväl monitorer som finlir med wait/notify. Om du fortfarande är inne på tanken med ha sensordatan i en array, varför inte en AtomicLongArray?

AtomicLongArray ala = new AtomicLongArray(3); ala.set(0, Double.doubleToLongBits(1.23456)); ala.set(1, Double.doubleToLongBits(2.34567)); ala.set(2, Double.doubleToLongBits(3.45678)); double d0 = Double.longBitsToDouble(ala.get(0)); // d0 = 1.23456 double d1 = Double.longBitsToDouble(ala.get(1)); // d1 = 2.34567 double d2 = Double.longBitsToDouble(ala.get(2)); // d2 = 3.45678

Om jag förstått ditt scenario rätt, kan detta gott och väl räcka? Det känns också som den enklaste formen av trådsäkring man kan göra.

Jag tolkar det som att klasserna du nämner ovan är monitorer. Jag kände dock inte till dem, men de verkar smidiga. Så jag håller med dig om att de bör användas. I övrigt kan det vara bra att veta hur man implementerar sådan funktionalitet.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av DeeXt
Jag tolkar det som att klasserna du nämner ovan är monitorer. Jag kände dock inte till dem, men de verkar smidiga. Så jag håller med dig om att de bör användas. I övrigt kan det vara bra att veta hur man implementerar sådan funktionalitet.

Jag tror att implementationerna till stora delar är plattformsspecifika, och där det finns möjlighet svarar en metod i en Atomic-klass direkt mot en atomär CPU-instruktion (såsom Compare-and-swap).

I grunden verkar Atomic*-klasserna vara wrappers runt en volatil klassmedlem, t.ex. en volatile long i fallet AtomicLong. Därtill använder de sig av klassen sun.misc.Unsafe för några spännande native-anrop. Så nej, inga monitorer i den meningen är inblandade. Nu kan det ju mycket väl förekomma någon form av finkorning låsning i implemenationen av Unsafe -dokumentationen av atomic-paketet varslar t.o.m. för det - men där det går jobbar de (precis som andra klasser i concurrent-paketet) utan lås.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av DeeXt
Med antagandet att värdena är av typen double, så citerar jag "Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications." från http://java.sun.com/docs/books/jls/third_edition/html/memory....

Jag tolkar det som att klasserna du nämner ovan är monitorer. Jag kände dock inte till dem, men de verkar smidiga. Så jag håller med dig om att de bör användas. I övrigt kan det vara bra att veta hur man implementerar sådan funktionalitet.

Ja, delat minnesutrymme vid skrivningar måste man givetvis synkronisera. Men bara för att själva array-pekaren är delad är det ingenting i hans lösning som behöver synkroniseras. Han vill ha en plats i arrayen som varje tråd skriver till helt enkelt, de skriver inte till samma minnesplatser. Ok, det skadar absolut inte om man är osäker att deklarera synchronized eller använda ett objekts monitorlås i en metod men min poäng var bara helt enkelt att det är onödigt.

[edit] läste din länk nu, det står mycket klart att det handlar om att synkronisera _skrivning_ till variablerna.

Permalänk
Medlem

erciz:
det är ett roligt projekt, lite därför som jag knappt sitter hemma vid datorn längre

Sensorerna är Ultraljud och ljussensorer (hela spektrumet) och plattformen är lejos nxt.

Just nu letar jag efter något liknande för hemmabruk