Just nu i M3-nätverket
Gå till innehåll

Trådproblem i j2me


Mattias Sandsäter

Rekommendera Poster

Mattias Sandsäter

Jag får ett fel när jag testar mitt program, det beror på att jag måste köra mina filsystemsoperationer i en egen tråd men jag är osäker på hur jag ska göra.

 

Jag har provat fram och tillbaks utan framgång och börjar bli lätt desperat. Jag har ett gäng metoder som öppnar vissa olika filtyper och i varje metod sker ett antal känsliga filsystemsoperationer. Sen är jag osäker på vad jag ska ha i run-metoden.

 

Är det bara det i run() som körs som egen tråd?

 

Har snart lagt en hel dag på att inte komma nån vart :(

 

[inlägget ändrat 2006-05-05 12:59:02 av Mattias Sandsäter]

Länk till kommentar
Dela på andra webbplatser

Trådar är rätt jobbiga grejer...är det absolut nödvändigt att använda det?

 

Just hur J2ME hanterar det vet jag inte, men i normalfallet så startas och avslutas den trådade exekveringen inuti public void run() ja, fast all metoder som anropas inifrån run() körs förstås i samma tråd. Det är lite svårt att ge några bra tips utan att veta vad du gör med dina filer, när, och vad du vill uppnå.

 

En rätt bra artikel om trådning i J2ME verkar http://developers.sun.com/techtopics/mobility/midp/articles/threading2/ vara.

 

Länk till kommentar
Dela på andra webbplatser

Mattias Sandsäter

Tvyärr måste jag tråda.

 

Att skapa tråden och sätta igång den är väl inget problem men jag måste få tag i informationen inne i tråden så att säga. Jag exemplifierar med det som krånglar precis nu.

 

Jag ska läsa in alla filnamn från en bestämd katalog. Då måste jag använda mig av Connector.open(url) som måste köras i egen tråd (i vart fall nu när jag lagt på mitt gui, innan funkade det utan). Det anropet returnerar en Connection som jag måste komma åt för att komma vidare när jag ska lista alla filer.

 

Det enda jag själv kommer på just nu är att den sätter en variabel som man hämtar via en annan metod men det känns inte som ett jättebra sätt? Särskilt inte då det finns ett antal känsliga metoder som måste trådas. Kommer ju explodera i hämtmetoder + att man ju måste kolla om det man hämtar blivit satt. Det kan ju ta olika tid att utföra den känsliga operationen.

 

Länk till kommentar
Dela på andra webbplatser

lizardKng

Har du tittat på wait() och notify()? De används för att synkronisera trådar.

 

Länk till kommentar
Dela på andra webbplatser

Mattias Sandsäter

Ska kolla in dom. Kom på följande, kan det funka?

 

Det jag måste fixa är då alltså att

Fixa väntegrejen i sista metoden

Fixa nåt som dödar tråden om ingen anropar för tillfället

 

Om jag gör klassen som en Singleton och håller räkningen via en static int så kan jag döda klassen när den blir noll?

 

public class ConnectionFactory implements Runnable{

private Connection c;

public void run(){
if(c==null){ c = getFromQueue().MakeSomething()}
else{vänta}
}

private void getFromQueue()

public synchronized Connection request(String url){
//put on queue
//wait for c to be done
conn = c;
c = null;
return conn;
}

}

 

 

 

[inlägget ändrat 2006-05-05 15:37:28 av Mattias Sandsäter]

Länk till kommentar
Dela på andra webbplatser

Mattias Sandsäter

Fyller på med en mer implementerad version. Kan det funka om jag fixar till dom ickeifyllda delarna?

 

 

 

[log]import javax.microedition.io.Connector;

import javax.microedition.io.file.*;

import java.io.IOException;

 

import java.util.*;

 

public class ConnectionFactory implements Runnable{

 

private Vector queue = new Vector();

private FileConnection fc;

private static ConnectionFactory connFactory;

 

 

private ConnectionFactory() {

}

 

public static ConnectionFactory getConnectionFactory() {

if (connFactory == null) {

connFactory = new ConnectionFactory();

}

return connFactory;

}

 

public void run(){

if(fc == null && !queue.isEmpty()){

String string = getFromQueue().toString();

try{

fc = (FileConnection)(Connector.open(string));

}catch(IOException ioe){

ioe.printStackTrace();

}

}else if(fc != null){

//Wait for work or wait for fetching of fc

}else{

//No work or requests. Die

}

}

 

private Object getFromQueue(){

return queue.firstElement();

}

 

public synchronized FileConnection request(String url){

queue.addElement(url);

//wait for c to be done

FileConnection conn = fc;

fc = null;

return conn;

}

 

 

 

 

 

 

 

 

}

[/log]

 

[inlägget ändrat 2006-05-05 17:13:25 av Mattias Sandsäter]

Länk till kommentar
Dela på andra webbplatser

lizardKng

Nja, *skeptisk*

 

Lite blandade tankar. OBS: Jag har aldrig använt J2ME utan vara J2SE.

 

- Du måste synkronisera access till kön, som det är nu synkroniserar du bara tillägg i kön, inte borttagning.

 

- Factorymetoden i ConnectionFactory returnerar en ConnectionFactory, den borde returnera en Connection (som inte finns, ännu). En ConnectionFactory är ju en fabrik som tillverkar Connections.

 

- Att använda toString() för att läsa ut URL:en känns också fel. toString ska användas t ex när man i debugsyfte vill få en strängrepresentation av ett objekt. I den nu icke existerande klassen Connection borde det då finnas en metod getUrl() eller liknande.

 

- Det finns ingen funktionalitet för att få en "användare" att vänta på att ens Connection blir klar.

 

 

 

Vad som borde ske är att när en användare lägger in en request ska den då göra wait() på sitt Connection-objekt. När Connection-objektet är klart med sin exkevering gör den notify() på sig själv och - vips - användaren kommer att väckas till liv och fortsätta exekvera.

 

 

Ingen uttömmande beskrivning men kanske ett halmstrå i alla fall.

 

[inlägget ändrat 2006-05-05 17:54:55 av lizardKng]

Länk till kommentar
Dela på andra webbplatser

Mattias Sandsäter

Jag är mycket tacksam för dina kommenterar. Jag hinner inte testa idag men återkommer så fort jag har gjort det.

 

Några små tankar kring dina tankar.

 

Måste jag verkligen göra något åt accessen till kön? Eftersom metoden är private och bara används inifrån run?

 

Minns inte riktigt varför jag gjorde connectionFactorygrejen, kanske funkar lika bra att göra en publik konstruktor.

 

Vad gäller toString() kan jag ju lika gärna använda en castning (String)

 

Threadklassen i J2ME är något begränsad, den har bara följande metoder

static int activeCount()

static Thread currentThread()

String getName()

int getPriority()

void interrupt()

boolean isAlive()

void join()

void run()

void setPriority(int newPriority)

static void sleep(long millis)

void start()

String toString()

static void yield()

 

Länk till kommentar
Dela på andra webbplatser

lizardKng

Kön används ju från metoden request() också, det är därför den behöver synkroniseras.

 

Du ska ju göra det du vill göra ;-) Vill du ha en factopry gör du en sån, vill du inte så gör du det inte.

 

Nej, du ska inte casta objektet, du ska skapa en metod för att returnera det data du vill ha, mycket tydligare på det viset.

 

Jag har som sagt inte använt J2ME. Det är ju iofs enkelt att ladda ner och kolla hur det ser ut, hmmm....... Det är dock inte mycket man behöver, starta en tråd och sedan synkronisera med wait() och notify(). Det är rätt märkligt hur mycket man kan göra med dessa få saker! Men att förstå dem är ju en grundförutsättning :)

 

Länk till kommentar
Dela på andra webbplatser

Mattias Sandsäter

Jag har kommit, om än en pytteliten bit, något längre. Men i nedanstående kod får jag IllegalMonitorStateException ( if the current thread is not the owner of the object's monitor). Testade även att köra wait() på queue. Tanken var ju att den skulle vänta där tills run() hade gjort sitt jobb med den.

 

Trådar var sannerligen inte helt enkelt, förhoppningsvis är jag proffs på det när jag löst alla mina problem.

 

public synchronized FileConnection request(String url){
	queue.addElement(url);
	try{
		queue.lastElement().wait();
	}catch(InterruptedException ie){
		ie.printStackTrace();
	}
	FileConnection conn = fc;
	fc = null;
	return conn;
}

 

Länk till kommentar
Dela på andra webbplatser

lizardKng

Hmm, kanske borde prova detta först men men... (det behövs eventuellt en try/catch runt synchronized)

 

public FileConnection request(String url){
synchronized(queue) {
queue.addElement(url);
}
try{
url.wait();
}catch(InterruptedException ie){
ie.printStackTrace();
}
FileConnection conn = fc;
fc = null;
return conn;
}

 

Och i den andra delen blir det nåt i stil med:

 

String url;
synchronized(queue) {
 url = getFromQueue();
}
//Do something with url.
url.notify();

[inlägget ändrat 2006-05-06 13:54:15 av lizardKng]

Länk till kommentar
Dela på andra webbplatser

Mattias Sandsäter

Nu tror jag att det funkar. Dock så fick jag ett annat problem med en annan filsystemsoperation, programmet stannar och frågar efter tillstånd att använda filsystemet, men när man trycker ja/nej så händer ingenting. Men trådproblemet kan nog anses vara löst hoppas jag. Tusen tack för den hjälpen.

 

public void run(){
	if(fc == null && !queue.isEmpty()){
		//System.out.println("Run, work to do");
		synchronized(queue){
			String url = getFromQueue().toString();
			//System.out.println("work under run with string:" + url);

			try{
				fc = (FileConnection)(Connector.open(url));
								}catch(IOException ioe){
				ioe.printStackTrace();
			}
			//System.out.println("work under run, fc set to" + fc);
			try{
				queue.notify();
			}catch(IllegalMonitorStateException imse){
				imse.printStackTrace();
			}
		}
	}els...

 

public FileConnection request(String url){

	synchronized(queue){
		queue.addElement(url);
		try{

			queue.wait();
		}catch(InterruptedException ie){
			ie.printStackTrace();
		}
	}

	FileConnection conn = fc;
	fc = null;

	return conn;
}

 

Länk till kommentar
Dela på andra webbplatser

lizardKng

OK, det var väl bra det. Det är ju lite att tänka på med trådar men har man bara lärt sig det är det rätt bra att ha :)

 

Länk till kommentar
Dela på andra webbplatser

Arkiverat

Det här ämnet är nu arkiverat och är stängt för ytterligare svar.

×
×
  • Skapa nytt...