Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
hallo,
ich suche etwas dasn ich als timer nehmen kann.
das ganze sollte so ablaufen. der timer läuft 30 sekunden bis er auf null ist. wenn er auf null ist soll er eine funktion ausführen. wenn er vorher , vor ablauf der 30 sekunden von einer anderen funktion gestartet wird dann fängt der timer wieder von vorne an zu laufen.
Stichwort Timer und Thread. Schau dir die Klassen an, such im Forum und schlage Tutorials nach . Wenn du dann noch ein konkretes Problem/Frage hast, zöger nicht sie hier zu stellen .
Ich hab das, ist schon recht lange her, in meinen Anfangszeiten mit nem Thread gelöst.. Hatte aber das "Problem" dass ich zu einer bestimmten Uhrzeit etwas ausführen wollte.
Hab dann einfach ausgerechnet wie lange das noch hin ist und hab den Thread erstmal so lange schlafen geschickt, und dann meine Aktion ausgeführt.
ich habe das grad versucht einzubinden.. aber ich glaub ich habe einen denkfehler gemacht.
also mein plan ist dieser:
ich habe in einer datenbank sagen wir 5 datensätze die alle auf true stehen. alle haben 30 sekunden zeit zum laufen. alle 15sek bekommt jeder datensatz das signal noch "da" zu sein. dann soll der timer von vorne beginnen.
falls dann bei einem datensatz einmal kein signal kommt soll dieser auf false stehen.
aber alle unabhängig voneinander.
MyThread mtArray[] = new MyThread[5];
for (int i = 0; i<5; i++){
mtArray[i] = new MyThread(sql[i]); // in sql sind deine abfragen auf die Datenbank gekapselt
mtArray[i].start();
}
Du kannst in den Konstruktor der Klasse MyThread das Objekt hineingeben, welches die Datenbankaufrufe für dich erledigt.
Code:
class MyThread exstends Thread{
private int time = 30 // sekunden
private boolean running = false;
private deineSQLWriterKlasse sql;/ / oder deine CheckKlasse
MyTread(deineSQLWriterKlasse sql ){
this.sql = sql;
}
public void start(){
if (time < 30) time = 30;
running = true
}
public void run(){
while (running){
sleepOneSec();
if (time == 15 ){
if (sql.bistDuDa()==true) {
timer=30;
} else {stelle auf false}
}
}
dieFunktion();
}
private void sleepOneSec(){
try
{
Thread.sleep(1000);
time--;
if (time == 0 ) running = false;
}
catch (Exception e) {}
}
}
Ich glaube du hast den Beispielcode nicht verstanden. Genau das macht der nämlich. Naja, fast. Das setzten des "noch da" Flags in der DB musst du in Zeile 16 -> dieFunktion(); machen. Und pro Datensatz einen solchen Thread erzeugen.
Das das Beispiel nicht die allumfassende Komplettlösung deines Problems darstellt ist klar, oder?
hallo, könnt ihr mir bitte nochmal helfen ?? ich komme damit nicht so ganz klar.
also:
Code:
if(level.equals("<199>")){
level = "Machine-Online";
System.out.println("Maschine: "+SsenderId+","+Stype+" online");
try {
CheckOnline mtArray[] = new CheckOnline[5];
for (int i = 0; i<Statusdaten.size(); i++){
// mtArray[i] = new CheckOnline(sql[i]); // in sql sind deine abfragen auf die Datenbank gekapselt
mtArray[i].start();
}
SqlData.setMachineOnline(SsenderId);
} catch (SQLException e) {e.printStackTrace();}
}
so habe ich das in meine "empfangsklasse" eingebunden. also ich muss nichts prüfen oder so.. die funktion "SqlData.setMachineOnline(SsenderId);" wird automatisch angetoßen sobald per socketverbindung die nachricht kommt.
irgendwo muss ich auch noch die machinenid übergeben die dann online bzw offline geschaltet werden muss.
public class CheckOnline extends Thread {
private int time = 30; // sekunden
private boolean running = false;
private deineSQLWriterKlasse sql;// oder deine CheckKlasse <<- ist das einfach die setMachineonline ?
public void start(){
if (time < 30) time = 30;
running = true;
}
public void run(){
while (running){
sleepOneSec();
if (time == 15 ){
if (sql.bistDuDa()==true) { // <<-- brauch ich das so ? weil das ganze wird ja erst angestoßen wenn die nachricht kommt !?
time=30;
} else {SqlData.delMachineOnline(null);}
}
}
SqlData.setMachineOnline(null);
}
if(level.equals("<199>")){
level = "Machine-Online";
System.out.println("Maschine: "+SsenderId+","+Stype+" online");
//SqlData.setMachineOnline(SsenderId);
CheckOnline mtArray[] = new CheckOnline[Statusdaten.size()];
for (int i = 0; i<Statusdaten.size(); i++){
mtArray[i] = new CheckOnline(Statusdaten.get(i).m_sender_id);
mtArray[i].start();
}
}
und:
Code:
public class CheckOnline extends Thread {
private int time = 30;
private boolean running = false;
String SenderId;
CheckOnline(String ssenderId ){
SenderId = ssenderId;
}
public void start(){
if (time < 30) time = 30;
running = true;
}
public void run(){
while (running){
sleepOneSec();
if (time == 15 ){
if (true/*wie soll ich hier das bist du da realisieren ? weil die funktion ja nur angeworfen wird wenn die
nachricht kommt ?!?! */) {
time=30;
} else
try {SqlData.delMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}
}
}
try {SqlData.setMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}
}
private void sleepOneSec(){
try
{
Thread.sleep(1000);
time--;
if (time == 0 ) running = false;
}
catch (Exception e) {}
}
}
habe alles nochma überarbeitet und hoffe das ihr mir jetzt weiterhelfen könnt.
also ich will erstma nur das es löuft. aber das tut es nicht. code sieht so aus :
Code:
public class CheckOnline extends Thread implements Runnable {
private int time = 30;
private boolean running = false;
String SenderId;
public static void main(String [] args){
Thread t1 = new Thread( new CheckOnline("36965") );
t1.start();
}
CheckOnline(String ssenderId ){
SenderId = ssenderId;
}
public void start(){
if (time < 30){
time = 30;
running = true;
}
}
public void run(){
while (running){
sleepOneSec();
if (time < 5 ){
try {SqlData.delMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}
}else{
try {SqlData.setMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}
time = 30;
}
}
}
private void sleepOneSec(){
try
{
Thread.sleep(1000);
time--;
if (time == 0 ){
running = false;
}
}
catch (Exception e) {}
}
}
das einzige was passiert wenn ich die klasse starte:
"The user operation is waiting for "Building Workspace" to complete.
dann so ein ladebalken --> 1 work items left.
dann kann ich des im hintergrund laufen lassen etc.
aber passieren tut nichts. egal wielange ich warte oder sonstiges.
Kein Plan, das ist ja nicht alles. Und ich bin ja auch kein Compiler.
Hast du Eclipse mal neu gestartet und/oder ein "clean project" gemacht? Kannst du ein simples "Hello World" Codebeispiel in Eclipse starten? Oder taucht das Phänomen bei allem auf was du zu starten versuchst?
deswegen dacht ich vllt das was mit dem code nicht stimmt. aber ich find den fehler nicht. zumal ich noch nicht so der spezi in threadprogrammierung bin.
reduziere dein Codebeispiel doch mal soweit dass man es ohne deine anderen klassen ausführen kann.. und dann googelst du mal nach "debugging" und "java".
public static void main(String [] args){
Thread t1 = new Thread( new CheckOnline("36965") );
t1.start();
}
Bei diesem Beispiel kann es passieren, bevor der t1 gestartet ist, ist dein "Main" Thread schon wieder vorbei.
probiere doch mal :
Code:
public static void main(String [] args){
Thread t1 = new Thread( new CheckOnline("36965") );
t1.start();
t1.join(); // dein MainThread wartet nun solange, bis t1 fertig ist.
}
Falls du noch mehrere Thread gestartet hast, wie eingangs erwähnt wurde :
Code:
public static void main(String [] args){
Thread t[] = new Thread[5];
for (int i = 0; i<5; i++){
Thread t[i] = new Thread( new CheckOnline("irgendeineNummer") );
t[i].start();
}
for (int i = 0; i<5; i++){
t[i].join(); // dein MainThread wartet nun solange, bis t1 fertig ist.
}
}
hab nur nen kleines weiteres problem. wenn es um mehrere threads geht.
also bei :
Code:
public static void timer() throws InterruptedException{
Thread t[] = new Thread[Statusdaten.size()];
for (int i = 0; i<Statusdaten.size(); i++){
Thread t[i] = new Thread( new CheckOnline("25697") );
t[i].start();
}
for (int i = 0; i<Statusdaten.size(); i++){
t[i].join(); // dein MainThread wartet nun solange, bis t1 fertig ist.
}
}
kommt er mit "Thread t = new Thread( new CheckOnline("25697") ); " nicht klar.. speziell darin das "t" er sagt nur. "syntax error. delete this token "i" ".
Du könntest auch ganz einfach den javax.swing.Timer benutzen
Delay Time und ActionListener kannst du ihm übergeben und auch per start(); starten oder per stop(); stoppen.
im Prinzip das selbe spiel mit den threads, nur das du dich nicht darum kümmern musst.
ist sicher einfacher für dich
public static void timer(String senderId) throws InterruptedException{
ArrayList<ReturnSqlMachineStatus> Statusdaten = SqlData.getSqlDataStatus();
Thread t[] = new Thread[Statusdaten.size()];
for (int i = 0; i<Statusdaten.size(); i++){
t[i] = new Thread(new CheckOnline(Statusdaten.get(i).m_sender_id));
}
for(int z=0;z<Statusdaten.size();z++){
if(Statusdaten.get(z).m_sender_id.equals(senderId)){
if(t[z].isAlive()){
time = 15;
}else{
t[z].start();
}
}
}
}
hmm... ich möchte falls der thread schon läuft mit dieser id. das die zeit einfach auf 15 wieder hochgesetzt wird. aber irgednwie startet er einen neuen thread der dann wieder von 15 an runterzählt...
EDIT:
ausserdem läuft er wenn ich 2x den selben thread starten will ins minus... er hört dann nicht mehr auf =(
thx
lass die das doch mal ausgeben
if(Statusdaten.get(z).m_sender_id.equals(senderId))
noch mals zum negativ problem.
MAch dir klar wass passiert, wenn 2 Threads auf die SELBE variable zugreifen, und BEIDE "GLEICHZEITIG" in der Zeile 75 ankommen. dann ist time = -1 evtl, wenn time vorher 1 war.
k besten dank. das mit dem static habe ich geändert.
wenn ich :
Code:
if (time <= 60){
time = 60;
running = true;
}
nicht das <= mache dann fängt er nicht an zu laufen. aber seitdem das static raus ist geht er auch nicht mehr ins minus. mein problem ist jetzt das wenn ich jetzt die timer funktion öfter starte dann macht er immer wieder einen neuen thread und setzt nicht die zeit einfach hoch wie er das soll.
if(t[z].isAlive()){
time = 15;
}else{
t[z].start();
}
Hier werden imm neu thread gestartet, da du diese Threads auch immer wieder neu erschaffen läßt...
(einige zeilen vorher)
Code:
Thread t[] = new Thread[Statusdaten.size()];
for (int i = 0; i<Statusdaten.size(); i++){
t[i] = new Thread(new CheckOnline(Statusdaten.get(i).m_sender_id));
}
Ich finde deine herangehensweise auch nicht so gut, da du die Timer Funktion static gemacht hast.
Mach dir die folgenden Klassen:
1. Main -> nur die main Methode
2. ThreadVerwaltung, wo deine timer Methode drin ist, und auch das Thread - Array.
3. deine ThreadKlasse.
es wird ein wenig übersichtlicher dadurch.
In einer Statischen Methode werden alla Variablen die du dort benutzt, aßer die Statischen, neu erschaffen. Das ist dein problem, da du, wenn die timer Methode verlässt, alle Thread nicht mehr zu fassen bekommst.
sucht er ja die stelle heraus an der die senderid steht die gerade gesendet wurde. also auch den thread mit der sender id.
wenn ich über thread[].isAlive jetzt abfrage ob genau dieser thread mit der soeben gesendeten is schon läuft. dann müsste man das doch so handlen können oder ?? wenn er läuft dann setz seine zeit wieder auf 60, wenn nicht dann starte ihn.
oder sollte ich dann ein time array erzeugen das dann auch immer nur genau die zeit die dem zugeordneten thread gehört dann wieder hochgesetzt wird ??
if(t[z].isAlive()){
time = 15;
}else{
t[z].start();
}
Zu deiner Frage:
Das Array wird immer wieder neu erzeugt, dahe kann dieser Thread ja nicht schon laufen.
Evtl soltest du deine Threads in ein Hashtable hineinpacken, dann weißt du immer, ob der schon mal gestartet wurde oder noch läuft oder überhaupt schon erzeugt wurde.
beispiel:
Code:
Hashtable<String,Thread> threadHT = new Hashtable<String,Thread>();
threadHT.put("DeineID",new Thread(ID).start()); // Erzeugen + hinzufügen +Starten ...
if (threadHT.get("deineID") == null) // -> Diese ID Existiert nicht -> Thread wurde noch nicht erzeugt
if (threadHT.get("deineID").isAlive()) // Dein Thread läut ....
// andernfalls ist er gestoppt .....
Dies soltest du in deiner umgebauten Form übernehmen.
#
Gruss
Warum so kompliziert? Ein einfacher Timer, gekapselt in einer Hilfsklasse wäre dafür vollkommen ausreichend und
weniger fehleranfällig als die ganze Thread-Akrobatik hier.
Irgendeine Hilfsklasse, die z.B. dieses Interface implementiert und dabei Timer/TimerTasks verwendet
Code:
public interface MyTimer
{
/*
* Task hinzufügen.
*
* @param id Id des Tasks
* @param timout Zeit bis zur Ausführung des Tasks in Millisekungen
* @param runnable Auszuführende Aktion
*/
void addTask(String id, long timeout, Runnable runnable);
/*
* Task mit gegebener Id zurücksetzen. Timer beginnt von vorne.
*
* @param id Id des Tasks
*/
void reset(String id);
/*
* Task mit gegebener Id abbrechen und entfernen.
*
* @param id Id des Tasks
*/
void cancel(String id);
}
Ja und wir sollen jetzt hellsehen wo der Fehler auftritt?
Wie wär's wenn du einen Stracktrace des Fehlers postest und die mit dem NullPointer in zusammenhang stehende Zeile nennst (nicht nur die nummer, sondern was drin steht)?
Hallo? Ich habs doch eben erklärt: Wir können nicht Hellsehen wo in den 80 Zeilen die du gepostet hast die Exception auftritt.
Oder vergisst du Satz 1 und 2 wieder wenn du den dritten Satz gelesen hast?
Zur Sache mit der NullPointerException:
Ein Beispiel:
Code:
String a = "hallo";
Der String ist NICHT NULL und hat eine Länge von 5.
Code:
String a = "";
Der String ist NICHT NULL und hat eine Länge von 0 (kein Zeichen im String, sprich leerer String).
Code:
String a;
Wenn du diese Variable jetzt irgendwie abfrägst, bevor du ihr einen Wert zugewiesen hast (egal ob "hallo" oder ""), dann bekommst du eine NullPointerException.
Ergo: Bevor man Variablen benutzt, muss man sie initielisieren.
So, und als letzten Satz, damit du dir's für den nächsten Post merken kannst:
Poste bitte die komplette Fehlermeldung mit allem drum und dran (angabe der Zeilen etc..) und dann schreib dazu welche Zeile (also der Code in der Zeile, nicht die Nummer) den Fehler verursacht hat.
du wirst mich jetzt wahrscheinlich fuer total bekloppt halten. aber ich habe keine ahnung wie ich das mache.
in der konsole steht nichts ausser dem was ich oben geschrieben habe.
ich bin mal im debugmodus durchgegangen. und er hört an dieser stelle auf
Ein Catch-Block eines "Try's" sollte entweder ein "e.printStackTrace();" enthalten, oder irgend etwas anderes zur korrekten Fehlerbehandlung. Wenn du nicht weißt wie du den Fehler behandeln sollst: Lass "e.printStackTrace();" drin stehen, dann sieht man wenigstens den Fehler.
Da du kein lauffähiges Minimalbeispiel gepostet hast, und den Rest des Prpgramms vorenthälst, kann ich dir nicht sagen wo der Fehler liegt dass dir kein korrekter StackTrace ausgegeben wird.
Wenn du Eclipse benutzt kannst du, im Debug-Modus, variablen und Objekte während der Ausführung markieren und im Kontextmenü (rechte Maustaste auf die markierte Variable) "watch" (im deutschen wohl "beobachten") auswählen. Dann siehst du welchen Wert die Variable hat.
Falls du ne andere IDE benutzt: Da muss es etwas ähnliches geben.
In der geposteten Codezeile steckt folgendes drin:
Statusdaten.get(p) ... Das ist das was deine get-Methode bei der initialisierung von sich gegeben hat. Da die Schleife begonnen wird, ist da also auch was in Statusdaten drin...
p ist ein Zähler, sollte also auch noch keine Probleme bereiten.
Aber was ist mit Statusdaten.get(p).m_sender_id ?? ist m_sender_id eine Public-Variable? Ist die vielleicht "null" ?
Wenn du schon debuggst, dann kannst du das ja mal "richtig" schritt für schritt durchgehen und auch die Variablen und Objekte checken.
if (threadHT.get(senderId) == null){
t[p].start();
}
if (threadHT.get(senderId).isAlive()){
time = 60;
}
So kannst du das auch nicht machen, da wenn erstes null ist , dann bleibt es auch weiterhin null!!
evtl:
Code:
if (threadHT.get(senderId) == null){ // gibt es keinen Thread
t[p] = new CopyOfCheckOnline (Statusdaten.get(p).m_sender_id) // dann erschaffe einen
threadHT.put(Statusdaten.get(p).m_sender_id,t[p]); // ab in die HJashtable damit
t[p].start(); // und starte ihn!
}
Code:
if (threadHT.get(senderId).isAlive()){
time = 60;
}
heißt soviel wie:
falls du noch da bist, also läufst, setze (bei wem auch immer) time auf 60.
Wie oben schon geschrieben, geht das so nicht.
Schreib die ne Main, eine Verwaltung für die Threads in einer EXTRA-Klasse wo die timer-Methode drin ist, UND eine ThreadKlasse...
ich fühle mich grade echt so als hätte ich noch nie programmiert ..
ich hoffe ihr helft mir trotzdem. bin so froh wenn ich das thread problem hinter mir habe.
vielen dank !!
meine main klasse:
Code:
public class testmain extends Thread implements Runnable {
public static void main (String [] args) throws InterruptedException{
String id = "36965";
String status_ = "2";
CopyOfCheckOnline bla = new CopyOfCheckOnline(id,status_);
bla.timer(id,status_);
}
}
meine Timer klasse:
Code:
public class Timer extends Thread implements Runnable {
private int time = 360;
private boolean running = false;
String SenderId;
String Status_;
Timer(String ssenderId,String status ){
SenderId = ssenderId;
Status_ = status;
}
public void start(){
if (time <= 360){
time = 360;
running = true;
}
}
public void run(){
start();
while (running){
sleepOneSec();
if (time < 1 ){
try {SqlData.delMachineOnline(SenderId);} catch (SQLException e) {e.printStackTrace();}
}
}
}
private void sleepOneSec( ){
try
{
Thread.sleep(1000);
time--;
System.out.println("Time: "+time);
if (time == 0 ){
running = false;
}
}
catch (Exception e) {}
}
}
die threadklasse:
Code:
public class CopyOfCheckOnline extends Thread implements Runnable {
String SenderId;
String Status_;
CopyOfCheckOnline(String ssenderId,String status ){
SenderId = ssenderId;
Status_ = status;
}
public void timer(String senderId,String Status) throws InterruptedException{
ArrayList<ReturnSqlMachineStatus> Statusdaten = SqlData.getSqlDataStatus();
Thread t[] = new Thread[Statusdaten.size()];
for(int e=0;e<Statusdaten.size();e++){
t[e] = new CopyOfCheckOnline (Statusdaten.get(e).m_sender_id, Status_);
}
Hashtable<String,Thread> threadHT = new Hashtable<String,Thread>();
for(int p=0;p<Statusdaten.size();p++){
if(Statusdaten.get(p).m_sender_id.equals(senderId)){
if (threadHT.get(senderId) == null){
t[p] = new Thread(new Timer(Statusdaten.get(p).m_sender_id,Status_));
threadHT.put(Statusdaten.get(p).m_sender_id,t[p]);
t[p].start();
}
// if (threadHT.get(senderId).isAlive()){
// time = 60;
// }
}}
try {SqlData.setMachineOnline(SenderId,Status_);} catch (SQLException e) {e.printStackTrace();}
}
}
das läuft jetzt soweit auch .
ich weiss nur nicht wie ich das mit der zeit machen soll.
also falls id vorhanden --> setze zeit wieder auf 60
danke
EDIT:
ich hab grad ma asuprobiert.. also wenn ich mehrmals die gleiche id schicke dann startet er trotzdem mehere threads und nicht nur fuer jede id einen einzigen .. =/
1) Die TestKlasse muss nicht von Thread ergeben und muss auch kein Interface implementieren
2) Wo startest du die ganzen Threads überhaupt?
3) Das ganze wäre einfacher zu verstehen wenn du dein Programm kommentieren würdest. In einem halben Jahr weißt du nämlich selbst nichtmehr was wie und vor allem warum funktioniert
4) Wieso bastelst du in der "timer" Methode ein Thread-Array, initialisierst es mit Instanzen von CopyOfCheckOnline und überschreibst den Inhalt unten wieder mit Instanzen von "Timer" ??
Irgenwie ist das stark verwirrend, oder ich schnall nicht was du da machst.