tutorials.de Buch-Aktion 05/2012
ERLEDIGT
JA
ANTWORTEN
8
ZUGRIFFE
949
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Avatar von Da_Chris
    Da_Chris Da_Chris ist offline Mitglied Platin
    Registriert seit
    Feb 2007
    Ort
    Augsburg
    Beiträge
    651
    Hallo Leute ich bin echt am verzweifeln wir sollen für Studium eine Planetensymulation umsetzen. Das ganze soll Thread basierend mit dem Master-Worker-Pattern ablaufen.
    Leider schläft mein Programm regelmässig ein und ich bin am Ende meines Lateins. (Ablaufdiagramme ohne Ende gezeichnet, zig sachen versucht etc...)
    Master:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    
    package planetary_server;
    import java.util.ArrayList;
    import java.util.List;
     
     
    public class Master {
        private Tasks tasks;
        private List<Worker> workerList = new ArrayList<Worker>();
        protected Object workerWaitDummy = new Object();
        public final double gravConst;
        public final double deltaT;
        public static final boolean debug = true;
     
        public Master(double deltaT, double gravConst) {
            if(Master.debug)
                System.err.println("Master()");     
            this.deltaT = deltaT;
            this.gravConst = gravConst;
            this.tasks = new Tasks();       
            this.buildWorker(getNumberOfProcessors());
        }
     
        private void buildWorker(int numCores) {
            if(Master.debug)
                System.err.println("Master.buildWorker()");
            for(int i = 0; i<numCores; i++) {
                Worker w = new Worker(i,this.tasks, this);
                w.start();
                this.workerList.add(w);
            }
        }
        
        
        public List<Planet> calculate(List<Planet> tasks) {
            if(Master.debug)
                System.err.println("Master.calculate("+tasks.toString()+")");
                
            this.tasks.setTasks(tasks);
            
            synchronized (this.workerWaitDummy) {
                System.err.println("- notifyAll workers");
                this.workerWaitDummy.notifyAll();
            }
            
            try {
                synchronized (this) {
                    if(!this.tasks.isFinished()) {
                        System.err.println("- wait master");
                        this.wait(); }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            List<Planet> results = this.tasks.getResults(); 
            
            return results;
        }
        
        /**
         * returns the number of available processors
         * 
         * @return availableProcessors
         */
        public static int getNumberOfProcessors() {
            if (debug)
                System.err.println("master.getNumberOfProcessors");
            Runtime runtime = Runtime.getRuntime();
            return runtime.availableProcessors();
        }
     
    }
    Worker:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    
    package planetary_server;
     
    public class Worker extends Thread {
        public final int id;
        private final Tasks tasks;
        private final Master master;
        public final double gravConst;
        public final double deltaT;
        
        public Worker(int id, Tasks tasks, Master master) {
            if(Master.debug)
                System.err.println("Worker("+id+", "+tasks+")");
            this.tasks = tasks;
            this.master = master;
            this.gravConst = master.gravConst;
            this.deltaT = master.deltaT;
            this.id = id;
        }
        
     
        @Override
        public void run() {
            if(Master.debug)
                System.err.println("Worker["+this.id+"].run()");
            
            try {
                synchronized (this.master.workerWaitDummy) {
                    this.master.workerWaitDummy.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
     
            while(true) {
                
                Planet task = this.tasks.getTask();
                
                if(task == null) {
                    
                    if(this.tasks.isFinished())
                        synchronized (this.master) {
                            System.err.println("- notify master");
                            this.master.notify();
                        }
                    try {
                        synchronized (this.master.workerWaitDummy) {
                            System.err.println("- wait worker");
                            this.master.workerWaitDummy.wait();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } 
                else {
                    
                    Planet result = this.calculate(task);
                    this.tasks.setResult(result);   
                    
                }
            }
        }
     
        private Planet calculate(Planet task) {
            if(Master.debug)
                System.err.println("Worker["+this.id+"].calculate("+task+")");
            return SolarSunSystem.calclateOnePlanet(task, this.tasks.getPlanetsOld(), this.deltaT, this.gravConst);
        }
        
    }
    Tasks:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    
    package planetary_server;
     
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
     
    public class Tasks {
        private List<Planet> planetsOld = new ArrayList<Planet>(); 
        private List<Planet> planetsNew = new ArrayList<Planet>(); 
        private Iterator<Planet> tasksIter = this.planetsOld.iterator();;
        
        public Tasks() {
            if(Master.debug)
                System.err.println("Tasks()");
        }
        
        protected void setTasks(List<Planet> tasks) {
            if(Master.debug)
                System.err.println("Tasks.setTasks("+tasks.toString()+")");
            this.planetsOld.clear();
            this.planetsNew.clear();
            this.planetsOld.addAll(tasks);
            this.tasksIter = this.planetsOld.iterator();
        }
        
        protected synchronized List<Planet> getResults() {
            if(Master.debug)
                System.err.println("Tasks.getResults()");
            return this.planetsNew;
        }
     
        protected synchronized Planet getTask() {
            if(Master.debug)
                System.err.println("Tasks.getTask()");
            if(this.tasksIter.hasNext())
                return this.tasksIter.next();
            else
                return null;
        }
        
        protected synchronized void setResult(Planet result) {
            if(Master.debug)
                System.err.println("Tasks.setResult("+result+")");
            this.planetsNew.add(result);
        }
        
        protected synchronized boolean isFinished() {
            if(Master.debug)
                System.err.println("Tasks.isFinished()  "+ (this.planetsNew.size()==this.planetsOld.size()?"true":"false"));
            return (this.planetsNew.size()==this.planetsOld.size());
        }
        
     
        public synchronized List<Planet> getPlanetsOld() {
            if(Master.debug)
                System.err.println("Tasks.getPlanetsOld()");
            return new ArrayList<Planet>(this.planetsOld);
        }
        
        
    }

    Und das kommt raus:
    Code :
    1
    2
    3
    4
    5
    6
    7
    
    Step 3 / 8766 complete! 00:01:378
    Master.calculate([id:0,name:Sonne,mass:1.99E30,pos:(16.39744466533697, 0.0025068520996454433, 0.0),speed:(0.0030365633197740683, 8.356172005683118E-7, 0.0), id:1,name:Merkur,mass:3.3E23,pos:(5.790769105713596E10, 5.173161802779882E8, 0.0),speed:(-427.58032436200176, 47898.72676009144, 0.0), id:2,name:Venus,mass:4.87E24,pos:(1.0893934757490266E11, 3.7853958015842587E8, 0.0),speed:(-120.81938929272617, 35049.86005257598, 0.0), id:3,name:Erde,mass:5.97E24,pos:(1.4959965401903943E11, 3.218398621968827E8, 0.0),speed:(-64.0705335843337, 29799.95406031698, 0.0), id:4,name:Mars,mass:6.42E23,pos:(2.2793985098675165E11, 2.6179196830871865E8, 0.0),speed:(-27.595044162058734, 24239.989435254887, 0.0), id:5,name:Jupiter,mass:1.9E27,pos:(7.785699872310099E11, 1.405079995730577E8, 0.0),speed:(-2.3646277908104945, 13009.99985768297, 0.0), id:6,name:Saturn,mass:5.68E26,pos:(1.4339999962174197E12, 1.0367999995099406E8, 0.0),speed:(-0.7004778751271509, 9599.99998348214, 0.0), id:7,name:Uranus,mass:8.68E25,pos:(2.8719999990586216E12, 7.34399999956323E7, 0.0),speed:(-0.1743292852883542, 6799.999998534666, 0.0), id:8,name:Neptun,mass:1.02E26,pos:(4.494999999615862E12, 5.864399999908857E7, 0.0),speed:(-0.07113678170395245, 5429.999999694501, 0.0)])
    Tasks.setTasks([id:0,name:Sonne,mass:1.99E30,pos:(16.39744466533697, 0.0025068520996454433, 0.0),speed:(0.0030365633197740683, 8.356172005683118E-7, 0.0), id:1,name:Merkur,mass:3.3E23,pos:(5.790769105713596E10, 5.173161802779882E8, 0.0),speed:(-427.58032436200176, 47898.72676009144, 0.0), id:2,name:Venus,mass:4.87E24,pos:(1.0893934757490266E11, 3.7853958015842587E8, 0.0),speed:(-120.81938929272617, 35049.86005257598, 0.0), id:3,name:Erde,mass:5.97E24,pos:(1.4959965401903943E11, 3.218398621968827E8, 0.0),speed:(-64.0705335843337, 29799.95406031698, 0.0), id:4,name:Mars,mass:6.42E23,pos:(2.2793985098675165E11, 2.6179196830871865E8, 0.0),speed:(-27.595044162058734, 24239.989435254887, 0.0), id:5,name:Jupiter,mass:1.9E27,pos:(7.785699872310099E11, 1.405079995730577E8, 0.0),speed:(-2.3646277908104945, 13009.99985768297, 0.0), id:6,name:Saturn,mass:5.68E26,pos:(1.4339999962174197E12, 1.0367999995099406E8, 0.0),speed:(-0.7004778751271509, 9599.99998348214, 0.0), id:7,name:Uranus,mass:8.68E25,pos:(2.8719999990586216E12, 7.34399999956323E7, 0.0),speed:(-0.1743292852883542, 6799.999998534666, 0.0), id:8,name:Neptun,mass:1.02E26,pos:(4.494999999615862E12, 5.864399999908857E7, 0.0),speed:(-0.07113678170395245, 5429.999999694501, 0.0)])
    - notifyAll workers
    Tasks.isFinished()  false
    - wait master
    - wait worker

    ich hoffe das ist nicht zuviel code aber ich steh grad voll auf dem schlauch und brauch dringend Hilfe!
    Danke schonmal!
     

  2. #2
    Avatar von zeja
    zeja zeja ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Sep 2006
    Beiträge
    2.962
    Sieht aus wie ein Deadlock

    Das Problem wird denke ich sein, dass wenn du dein wait im synchronized Block ausführst, wird der Block nicht verlassen. Das Objekt ist als gelocked und das notify kann nicht durchgeführt werden. Das kannst du ja mal anhand von ein paar Ausgaben testen.
     

  3. #3
    THMD THMD ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Beiträge
    122
    Moin,

    versuch doch mal bitte, die setTasks(List<Planet> tasks) Methode zu synchronisieren. Du änderst dort den Zustand des Tasks-Objekt, welches sowohl vom Master als auch den Workern benutzt wird. Da diese Zustandsänderung unsynchronisiert erfolgt, ist nicht sichergestellt, dass sie in einem anderen Thread auch sichtbar ist. Das würde zumindest erklären warum er im Worker in die if (task==null) Bedingung springt und sich dort schlafen legt.

    Aus diesem Schlaf wird er auch nicht wieder erweckt, da nirgendwo mehr ein notify() auf das entsprechende Monitor-Objekt aufgerufen wird.

    Grüße
    THMD
     
    If Java had true garbage collection, most programs would delete themselves upon execution. (Robert Sewell)

  4. #4
    Avatar von Da_Chris
    Da_Chris Da_Chris ist offline Mitglied Platin
    Registriert seit
    Feb 2007
    Ort
    Augsburg
    Beiträge
    651
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    
    Step 3 / 8766 complete! 00:01:003
    Master.calculate([id:0,name:Sonne,mass:1.99E30,pos:(16.39744466533697, 0.0025068520996454433, 0.0),speed:(0.0030365633197740683, 8.356172005683118E-7, 0.0), id:1,name:Merkur,mass:3.3E23,pos:(5.790769105713596E10, 5.173161802779882E8, 0.0),speed:(-427.58032436200176, 47898.72676009144, 0.0), id:2,name:Venus,mass:4.87E24,pos:(1.0893934757490266E11, 3.7853958015842587E8, 0.0),speed:(-120.81938929272617, 35049.86005257598, 0.0), id:3,name:Erde,mass:5.97E24,pos:(1.4959965401903943E11, 3.218398621968827E8, 0.0),speed:(-64.0705335843337, 29799.95406031698, 0.0), id:4,name:Mars,mass:6.42E23,pos:(2.2793985098675165E11, 2.6179196830871865E8, 0.0),speed:(-27.595044162058734, 24239.989435254887, 0.0), id:5,name:Jupiter,mass:1.9E27,pos:(7.785699872310099E11, 1.405079995730577E8, 0.0),speed:(-2.3646277908104945, 13009.99985768297, 0.0), id:6,name:Saturn,mass:5.68E26,pos:(1.4339999962174197E12, 1.0367999995099406E8, 0.0),speed:(-0.7004778751271509, 9599.99998348214, 0.0), id:7,name:Uranus,mass:8.68E25,pos:(2.8719999990586216E12, 7.34399999956323E7, 0.0),speed:(-0.1743292852883542, 6799.999998534666, 0.0), id:8,name:Neptun,mass:1.02E26,pos:(4.494999999615862E12, 5.864399999908857E7, 0.0),speed:(-0.07113678170395245, 5429.999999694501, 0.0)])
    Tasks.setTasks([id:0,name:Sonne,mass:1.99E30,pos:(16.39744466533697, 0.0025068520996454433, 0.0),speed:(0.0030365633197740683, 8.356172005683118E-7, 0.0), id:1,name:Merkur,mass:3.3E23,pos:(5.790769105713596E10, 5.173161802779882E8, 0.0),speed:(-427.58032436200176, 47898.72676009144, 0.0), id:2,name:Venus,mass:4.87E24,pos:(1.0893934757490266E11, 3.7853958015842587E8, 0.0),speed:(-120.81938929272617, 35049.86005257598, 0.0), id:3,name:Erde,mass:5.97E24,pos:(1.4959965401903943E11, 3.218398621968827E8, 0.0),speed:(-64.0705335843337, 29799.95406031698, 0.0), id:4,name:Mars,mass:6.42E23,pos:(2.2793985098675165E11, 2.6179196830871865E8, 0.0),speed:(-27.595044162058734, 24239.989435254887, 0.0), id:5,name:Jupiter,mass:1.9E27,pos:(7.785699872310099E11, 1.405079995730577E8, 0.0),speed:(-2.3646277908104945, 13009.99985768297, 0.0), id:6,name:Saturn,mass:5.68E26,pos:(1.4339999962174197E12, 1.0367999995099406E8, 0.0),speed:(-0.7004778751271509, 9599.99998348214, 0.0), id:7,name:Uranus,mass:8.68E25,pos:(2.8719999990586216E12, 7.34399999956323E7, 0.0),speed:(-0.1743292852883542, 6799.999998534666, 0.0), id:8,name:Neptun,mass:1.02E26,pos:(4.494999999615862E12, 5.864399999908857E7, 0.0),speed:(-0.07113678170395245, 5429.999999694501, 0.0)])
    - notifyAll workers
    Tasks.isFinished()  false
    - wait master
    Exception in thread "main" java.lang.IllegalMonitorStateException
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:485)
        at planetary_server.Master.calculate(Master.java:49)
        at planetary_server_test.MasterTest.main(MasterTest.java:71)
    Tasks.getTask()
    Worker[0].calculate(id:0,name:Sonne,mass:1.99E30,pos:(16.39744466533697, 0.0025068520996454433, 0.0),speed:(0.0030365633197740683, 8.356172005683118E-7, 0.0))
    Tasks.getPlanetsOld()
    Tasks.setResult(id:0,name:Sonne,mass:1.99E30,pos:(29.15100809803085, 0.007019182022325505, 0.0),speed:(0.004048749698389197, 1.6712327564761668E-6, 0.0))
    Tasks.getTask()
    Worker[0].calculate(id:1,name:Merkur,mass:3.3E23,pos:(5.790769105713596E10, 5.173161802779882E8, 0.0),speed:(-427.58032436200176, 47898.72676009144, 0.0))
    Tasks.getPlanetsOld()
    Tasks.setResult(id:1,name:Merkur,mass:3.3E23,pos:(5.790589522812688E10, 6.897493047961549E8, 0.0),speed:(-570.1024584658559, 47897.453527778904, 0.0))
    Tasks.getTask()
    Worker[0].calculate(id:2,name:Venus,mass:4.87E24,pos:(1.0893934757490266E11, 3.7853958015842587E8, 0.0),speed:(-120.81938929272617, 35049.86005257598, 0.0))
    Tasks.getPlanetsOld()
    Tasks.setResult(id:2,name:Venus,mass:4.87E24,pos:(1.0893884013382988E11, 5.0471882444221354E8, 0.0),speed:(-161.0923178107252, 35049.72010508385, 0.0))
    Tasks.getTask()
    Worker[0].calculate(id:3,name:Erde,mass:5.97E24,pos:(1.4959965401903943E11, 3.218398621968827E8, 0.0),speed:(-64.0705335843337, 29799.95406031698, 0.0))
    Tasks.getPlanetsOld()
    Tasks.setResult(id:3,name:Erde,mass:5.97E24,pos:(1.49599384922871E11, 4.291196141146546E8, 0.0),speed:(-85.42733777179316, 29799.90811622294, 0.0))
    Tasks.getTask()
    Worker[0].calculate(id:4,name:Mars,mass:6.42E23,pos:(2.2793985098675165E11, 2.6179196830871865E8, 0.0),speed:(-27.595044162058734, 24239.989435254887, 0.0))
    Tasks.getPlanetsOld()
    Tasks.setResult(id:4,name:Mars,mass:6.42E23,pos:(2.2793973508757523E11, 3.490559112576199E8, 0.0),speed:(-36.793387183683286, 24239.978869690254, 0.0))
    Tasks.getTask()
    Worker[0].calculate(id:5,name:Jupiter,mass:1.9E27,pos:(7.785699872310099E11, 1.405079995730577E8, 0.0),speed:(-2.3646277908104945, 13009.99985768297, 0.0))
    Tasks.getPlanetsOld()
    Tasks.setResult(id:5,name:Jupiter,mass:1.9E27,pos:(7.785699772995732E11, 1.8734399880454132E8, 0.0),speed:(-3.1528370441359286, 13009.999715363485, 0.0))
    Tasks.getTask()
    Worker[0].calculate(id:6,name:Saturn,mass:5.68E26,pos:(1.4339999962174197E12, 1.0367999995099406E8, 0.0),speed:(-0.7004778751271509, 9599.99998348214, 0.0))
    Tasks.getPlanetsOld()
    Tasks.setResult(id:6,name:Saturn,mass:5.68E26,pos:(1.4339999932754126E12, 1.382399998615238E8, 0.0),speed:(-0.9339704996338387, 9599.999966812155, 0.0))
    Tasks.getTask()
    Worker[0].calculate(id:7,name:Uranus,mass:8.68E25,pos:(2.8719999990586216E12, 7.34399999956323E7, 0.0),speed:(-0.1743292852883542, 6799.999998534666, 0.0))
    Tasks.getPlanetsOld()
    Tasks.setResult(id:7,name:Uranus,mass:8.68E25,pos:(2.8719999983264385E12, 9.791999998770535E7, 0.0),speed:(-0.2324390470341635, 6799.999997061469, 0.0))
    Tasks.getTask()
    Worker[0].calculate(id:8,name:Neptun,mass:1.02E26,pos:(4.494999999615862E12, 5.864399999908857E7, 0.0),speed:(-0.07113678170395245, 5429.999999694501, 0.0))
    Tasks.getPlanetsOld()
    Tasks.setResult(id:8,name:Neptun,mass:1.02E26,pos:(4.494999999317088E12, 7.819199999743634E7, 0.0),speed:(-0.09484904227010095, 5429.999999387594, 0.0))
    Tasks.getTask()
    Tasks.isFinished()  true
    - notify master
    - wait worker
    ich habe den synchronized block um das wait im master weggenommen und die funktion setTasks auch auf synchronized gestellt....
    Jetzt bekomme ich sogar eine IllegalMonitorStateException.

    Der Synchronized Block is nun wieder drin um die IllegalMonitorStateException zu verhindern.
    Was komisch ist ich hab fast exakt das selbe Thread Beispiel mit einfachen doubles umgesetzt die er quadriert damit funktioniert das Threading einwandfrei...... und das soll man verstehen?
    Geändert von Da_Chris (18.11.09 um 13:03 Uhr)
     

  5. #5
    THMD THMD ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Beiträge
    122
    Hallo,
    Zitat Zitat von Da_Chris Beitrag anzeigen
    ich habe den synchronized block um das wait im master weggenommen
    der Aufruf von wait() außerhalb eines synchronized Blocks ist nicht möglich, führt immer zu einer Exception.

    Zitat Zitat von Da_Chris Beitrag anzeigen
    Der Synchronized Block is nun wieder drin um die IllegalMonitorStateException zu verhindern.
    ok, und läuft es jetzt? oder geht es immer noch schief?
    Zitat Zitat von Da_Chris Beitrag anzeigen
    Was komisch ist ich hab fast exakt das selbe Thread Beispiel mit einfachen doubles umgesetzt die er quadriert damit funktioniert das Threading einwandfrei...... und das soll man verstehen?
    Willkommen in der Welt des Java Multithreading. Vielleicht kannst du ja mal das ganze Beispiel zippen und posten, dann wäre es leichter ausprobierbar .

    Wenn es keine Uni-Aufgabe wäre um das Pattern zu verstehen hät ich gesagt, benutz Callables, aber ich denke das ist nicht im Sinne des Aufgabenstellers.

    Gruß
    THMD
     
    If Java had true garbage collection, most programs would delete themselves upon execution. (Robert Sewell)

  6. #6
    Avatar von Da_Chris
    Da_Chris Da_Chris ist offline Mitglied Platin
    Registriert seit
    Feb 2007
    Ort
    Augsburg
    Beiträge
    651
    Naja ich bekomm keine exception mehr aber es schläft trotzdem imnmer ein

    Lerneffekt hin oder her ich arbeite jetzt schon seit Donnerstag an dem Problem und langsam ist die frustration größer als der spass dran

    Ich hab mal beide Beispiele gezipt und angehängt
    Angehängte Dateien Angehängte Dateien
    Geändert von Da_Chris (18.11.09 um 14:44 Uhr)
     

  7. #7
    THMD THMD ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Beiträge
    122
    Hallo,

    Zitat Zitat von Da_Chris Beitrag anzeigen
    ...
    Lerneffekt hin oder her ich arbeite jetzt schon seit Donnerstag an dem Problem und langsam ist die frustration größer als der spass dran ...
    durchaus verständlich. Also ich hab mir dein Programm mal angesehen. Mal abgesehen davon, dass ich nur grob eine Ahnung hab, was er da berechnet - du hast da diverse Probleme (mindestens zwei). Ich habs ein paar mal durchlaufen lassen und bei mir sind folgende Fehler aufgetreten - es lief aber auch ein paar mal durch

    Problem Nr. 1 - gar nix startet
    Beim erstellen deines Masters erzeugst du direkt die Worker und startest sie. In der run() Methode der Worker rufst du ganz am Anfang wait() auf this.master.workerWaitDummy auf. In der calculate Methode des Workers rufst du nach dem Setzen der Tasks entsprechend ein notifyAll() auf diesem Monitorobjekt auf. Ich vermute mal dadurch sollen ganz am Anfang die Worker gleichzeitig loslaufen. Das funktioniert aber nicht immer, da man nicht sicher sagen kann, wann der erste Befehl innerhalb der run-Methode der Worker ausgeführt wird. Durch unglückliches Timing kann es sein, dass die Worker gestartet werden, aber das wait() in der run Methode nicht sofort ausgeführt wird. Der Master setzt die Tasks, ruft notifyAll() auf un d erst jetzt werden die wait() Aufrufe der Worker ausgeführt. Ergebniss: alle Worker warten und nichts tut sich.

    Problem Nr.2 - planetsNew wird zu groß
    Wenn du bei der isFinished() Abfrage auch mal die Größen der beiden Listen ausgeben läßt, wirst du den Fall bekommen, dass planetsNew größer als planetsOld ist, womit isFinished() false zurückgibt, aber keine alten Planeten mehr da sind - es bleibt stehen. Auch hier ist der Grund wahrscheinlich unglückliches Timing, wobei folgende Beispiel nur ein Erklärungsversuch ist (ohne Garantie auf absolute Korrektheit) - ich habs mir jetzt mal so hergeleitet.

    Nehmen wir mal an mehrere Worker (4) arbeiten Tasks ab. Zwei Worker haben gerade die letzten Tasks erledigt und den Result gesetzt. Jetzt werden zwei andere Worker aktiviert. Die versuchen sich einen Task zu holen -> keiner mehr da. Sie gehen also in die if(task==null) Bedingung und rufen beide nacheinander isFinished() auf, das true liefert (Result wurde von den anderen Workern gesetzt)
    Code :
    1
    2
    3
    4
    5
    6
    
    if(this.tasks.isFinished())
           // WORKER BEIDE HIER
        synchronized (this.master) {
            System.err.println("- notify master");
            this.master.notify();
        }
    Jetzt wird ein Worker vom System supendiert und der andere betritt den synchronized Block, woraufhin der Master mit notify() geweckt wird und auch direkt die Kontrolle übernimmt. (Ein Worker steht immer noch zwischen isFinished() und synchronized!). Der aktivierte Master gibt das Result zurück und wir befinden uns wieder im Test. (Worker ist immer noch inaktiv). Der Test ruft auf dem Master die calculate Method auf und setzt die Task neu. Die anderen Worker holen sich neue Task, der Master wartet wieder auf ein Signal und jetzt wird plötzlich unser inaktiver Worker vom System wiedererweckt. Er betritt jetzt den synchronized Block und schickt dem Master ein entsprechendes Signal. Der glaubt das alles i.o. ist und gibt das Result (leere Liste) an den Test, der Test ruft wieder calculate auf und eine neue Taskliste wird erstellt. Dummerweise haben die anderen Worker aber immer noch die Tasks aus der alten Liste, die sie brav als Result setzen. Damit wird die planetsNew Liste größer als sie sein soll und damit bleibt er hängen.

    Ich hoffe es war halbwegs verständlich. Wie gesagt das Verhalten muss nicht auftreten, kann aber - ist halt Multithreading - und in deinem Fall noch mit wait() und notify() - brrrrr
    Fall du auch was anderes als wait() und notify() verwenden darfst, schau dir mal das java.util.concurrent Package an. Da gibt es Konstrukte, die dir das Programmieren von Multithreading-Anwendungen erheblich vereinfachen. Dein Beispiel könnte man z.B. relativ fix mit CountDownLatches umsetzen.

    Ach ja, wenn du dein eigentliches Problem gelöst hat - wenn das Programm fertig ist, beendet sich die VM nicht, da deine Worker aufgrund von while(true) nicht beendet werden. Das solltest du vielleicht über nen Flag steuern.

    Grüße
    THMD
     
    If Java had true garbage collection, most programs would delete themselves upon execution. (Robert Sewell)

  8. #8
    Avatar von Da_Chris
    Da_Chris Da_Chris ist offline Mitglied Platin
    Registriert seit
    Feb 2007
    Ort
    Augsburg
    Beiträge
    651
    Danke schonmal werde mir das Package ansehen.

    Problem 1 tritt eigetnlich nie auf und auch problem 2 konnte ich nicht beobachten. Ich hätte dazu sagen müssen das ich master.calculate() immer wieder anstoße in einer schleife. Die Berechneten Planeten werden dann erneut als eingabe verwendet. Die Berechnung führt exakt einen Schritt aus. Zusammen ergibt das dann eine Planetensymulation.
    Das Problem ist vermutlich das die Worker das notify auf den master kurz vor dem wait des masters ausführen.....

    Das komische ist das mein Threads Beispiel einwandfrei funktioniert wobei Planets nicht funktioniert obwohl ich dabei exakt das selbe verwendet habe.

    Naja ich seh mir jetzt das package mal an ich hoffe ich komm damit dann zurecht...
    Geändert von Da_Chris (19.11.09 um 01:35 Uhr)
     

  9. #9
    Avatar von Da_Chris
    Da_Chris Da_Chris ist offline Mitglied Platin
    Registriert seit
    Feb 2007
    Ort
    Augsburg
    Beiträge
    651
    juhuu es geht.
    Gelöst hab ichs mit CountDownLatches (was eine wirklich klasse Klasse ist!) und einer BlockingQueue
    Herzlichsten Dank!
     
    Google und die Forensuche beantworten 50% aller Fragen!
    Pflichtlektüre: Das PHP Handbuch als Windows Help Datei

    Bitte Benutzt für Source-Code immer die richtigen Formatierungstags:
    [PHP]Für PHP diese Tags[\PHP] ... [HTML]Für HTML diese Tags[\HTML] ... [SQL]Für SQL diese Tags[\SQL] ... [CODE]Für sonstigen Code[\CODE]

    Wenn mein Beitrag hilfreich war bitte ich um eine positive Bewertung.

Ähnliche Themen

  1. Web Worker - Layoutprozess und Zeichnen in Canvas
    Von Danielku15 im Forum Javascript & Ajax
    Antworten: 0
    Letzter Beitrag: 10.12.10, 11:01
  2. Worker Lebensdauer
    Von klanawagna im Forum Javascript & Ajax
    Antworten: 0
    Letzter Beitrag: 30.08.10, 09:51
  3. Perl: Boss/Worker-Threads
    Von H3llGhost im Forum CGI, Perl, Python, Ruby, Power Shell
    Antworten: 0
    Letzter Beitrag: 15.11.09, 20:00
  4. PhpMyAdmin mit Apache MPM Worker
    Von benjaminbih im Forum PHP
    Antworten: 3
    Letzter Beitrag: 14.09.08, 12:18
  5. sql2005.master <--> sql2000.master
    Von TurnMeOn im Forum Relationale Datenbanksysteme
    Antworten: 0
    Letzter Beitrag: 03.01.06, 10:14