• Es freut uns dass du in unser Minecraft Forum gefunden hast. Hier kannst du mit über 130.000 Minecraft Fans über Minecraft diskutieren, Fragen stellen und anderen helfen. In diesem Minecraft Forum kannst du auch nach Teammitgliedern, Administratoren, Moderatoren , Supporter oder Sponsoren suchen. Gerne kannst du im Offtopic Bereich unseres Minecraft Forums auch über nicht Minecraft spezifische Themen reden. Wir hoffen dir gefällt es in unserem Minecraft Forum!

PlugIn For-Schleife bringt Server zum Laggen? Bitte was?

MaxDerVerpeilte

Redstoneengineer
Registriert
30 Juni 2017
Beiträge
34
Alter
38
Diamanten
300
Guten Tag!
Ich erzähle zunächst mein Problem: Ich programmierte ein Countdown Plugin, welches auch Funktioniert. Allerdings kann in der Zeit, in der der Countdown im Chat steht nichts auf dem Server gemacht werden (Geschrieben, Gebaut etc.). Ich nutze um den Countdown möglich zumachen eine For-Schleife, die wiefolgt aussieht:

Code:
 if(n == 1){
    for (int i=c; i>0; i--){
         Bukkit.broadcastMessage(countdown.pr + " §6---§b " + i + " §6---");
         try {
              Thread.sleep(1000);
         } catch (InterruptedException e) {
               e.printStackTrace();
         }
     }
  }
n steht in meinem Fall für den Zeitabstand, der Zwischen den "Counts" stehen soll und c ist die Zahl, von der der Countdown starten soll.
 
Zuletzt bearbeitet:

IDK_WHO_AM_I

Kuhfänger
Registriert
30 Mai 2017
Beiträge
66
Alter
28
Diamanten
300
Minecraft
IDK_WHO_AM_I
Also was @jensIO geschrieben hat stimmt aber damit du es verstehst, weil ich vermute du weißt nicht was damit gemeint ist.

Wenn du Thread.sleep(1000); machst dann pausierst du nicht nur deinen Code sondern auch den Thread auf dem der Code läuft und das ist leider der Server Mainthread xD

Also machst du folgendes:

Code:
new Thread() {
  for(int i=0;i<100;i++) {
    //Was du machen willst :D
  };

}.start()

Bei dir sollte es dann etwa so aussehen:

Code:
 if(n == 1){
    new Thread() {
      for (int i=c; i>0; i--){
           Bukkit.broadcastMessage(countdown.pr + " §6---
  §b " + i + " §6---");
           try {
                Thread.sleep(1000);
           } catch (InterruptedException e) {
                 e.printStackTrace();
           }
      }.start();
     }
  }
 

FelixKlauke

Erzengel
Ehem. Teammitglied
Registriert
5 Januar 2014
Beiträge
1.038
Diamanten
299
Minecraft
FelixKlauke

MaxDerVerpeilte

Redstoneengineer
Registriert
30 Juni 2017
Beiträge
34
Alter
38
Diamanten
300
Jo, ne Scheduler kannte ich bis jetzt noch gar nicht bei dem Informatik Unterricht in der Schule xD
Wenn du mir mal erklären könntest wie die funktioniert, wäre das echt nett, weil ich Blick da nicht durch xD

+ @zM4xi vielen Dank erstmal, aber:
6ef12e7067832b4b25827c41e48bd19c.png


das sieht nicht so gut aus.
 
Zuletzt bearbeitet:

jens1o

Workaholic
Registriert
28 Juli 2015
Beiträge
644
Alter
23
Diamanten
254
Minecraft
jens1o
Dann lagere es in eine weitere Klasse aus, wenn du mit der Gestaltung unzufrieden bist?

Informatik ist viel Englisch, was hast du konkret an der Erklärung nicht verstanden?
 
Zuletzt bearbeitet:

IDK_WHO_AM_I

Kuhfänger
Registriert
30 Mai 2017
Beiträge
66
Alter
28
Diamanten
300
Minecraft
IDK_WHO_AM_I
Code:
        new Thread() {
            public void run() {
                for (int i=c; i>0; i--) {
                       Bukkit.broadcastMessage(countdown.pr + " §6--- §b " + i + " §6---");
                       try {
                            Thread.sleep(1000);
                       } catch (InterruptedException e) {
                             e.printStackTrace();
                       }
                  }
            };
        }.start();

So jetzt stimmts da hat das run() gefehlt xD
 

MaxDerVerpeilte

Redstoneengineer
Registriert
30 Juni 2017
Beiträge
34
Alter
38
Diamanten
300
Jo das Klappt, ich danke dir vielmals!
und @jensIO
Ja ich lerne programmieren grade noch, bin dabei auf mich allein gestellt und habe nur den Informatik Unterricht in der Schule um was aufzugreifen, ich versuche so weit ich es kann zu kommen, wenn ich nichts finde Google ich und bei ganz speziellen Fragestellungen wie dieser hier, habe ich halt nur des Forum
 

IDK_WHO_AM_I

Kuhfänger
Registriert
30 Mai 2017
Beiträge
66
Alter
28
Diamanten
300
Minecraft
IDK_WHO_AM_I
Falls du selber mal über das Problem nachgedacht hättest, wüsstest du, dass man mit dem Scheduler nicht die For Schleife pausieren will. ;)

Ich weiß das war auch keine Antwort an den Autor sondern an @SasukeKawaii
Ich werfe mal den Scheduler ( http://bukkit.gamepedia.com/Scheduler_Programming ) in den Raum, der dafür gerne verwendet wird und auch genau für sowas vorgesehen ist. Auch ruhig mal https://hub.spigotmc.org/javadocs/spigot/org/bukkit/scheduler/BukkitScheduler.html ansehen.

Hier mal ein Beispiel:

Javascript:
        for(int i=0; i<50;i++) {
            Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
                @Override
                public void run() {
                    System.out.println("Nummer: " + i);
                }
            }, 20L);
        }

Man hat zwar eine verzögerte Ausgabe hat jedoch sind alle Ausgaben um 1 Sekunde verzögert und werden dann mit dem selben Abstand ziwschen einander ausgegeben weil zwar die DelayedScheduler erzeugt werden aber halt mit einem Abstand von der Geschwindigkeit der "For Schleife".
Also selbes Ergebnis wie bei eine normalen Schleife.
 

UnityGaming

Workaholic
Registriert
25 Oktober 2015
Beiträge
527
Alter
26
Diamanten
312
Minecraft
FastFelix771
Also so wie ich das sehe werden 50 Tasks registriert die alle in der selben Sekunde danach ausgeführt werden.
Also 50 -> 0 in 1 Sekunde.

How about this:

Code:
 for(int i=0; i<50;i++) {
            Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
                @Override
                public void run() {
                    System.out.println("Nummer: " + i);
                }
            }, 20L * i);
        }

Diese Art von Lösung finde ich aber ehrlich gesagt nicht sonderlich galant.

Aber dieser Thread verwirrt mich ein wenig.
Was genau ist denn jetzt das Ziel? Etwa bloß ein Countdown im Chat während alles andere wie gehabt weiter läuft?
 

moinless

Schafhirte
Registriert
4 Oktober 2013
Beiträge
103
Diamanten
302
Was ist denn an einem Scheduler nicht elegant? oO

Sein Ziel ist ein Countdown, welcher im Chat ab läuft -> Siehe Anfangspost

Die einfachste und simpelste Möglichkeit dafür wäre folgendes:

Code:
        Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new BukkitRunnable(){

            @Override
            public void run(){
                Bukkit.broadcastMessage(countdown.pr + " §6---§b " + i + " §6---");

                i--;
            }


        },20L * i);
 

UnityGaming

Workaholic
Registriert
25 Oktober 2015
Beiträge
527
Alter
26
Diamanten
312
Minecraft
FastFelix771
Was ist denn an einem Scheduler nicht elegant? oO
Der Scheduler ist elegant.
Er ist ja auch genau für solche Spielereien da.
Die Umsetzung mit den 50 Schedulern finde ich eher weniger prickelnd.

Die einfachste und simpelste Möglichkeit dafür wäre folgendes:
Bloß würde dieser Task weiter und weiter und weiter laufen... bis ins unendliche.

Hier wäre mein Beispiel:

Code:
    public void countdown(Plugin plugin, Runnable runnable, int seconds) {
        AtomicInteger counter = new AtomicInteger(0);
        AtomicReference<BukkitTask> taskRef = new AtomicReference<BukkitTask>(null);

        BukkitTask bukkitTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
            int current = counter.getAndIncrement();
            Bukkit.broadcastMessage("Self destruction in T- " + current);
            if (current < seconds) return;

            BukkitTask task = taskRef.getAndSet(null);
            if (task == null) return;

            Bukkit.getScheduler().runTaskLater(plugin, runnable, 1L);
            Bukkit.getScheduler().cancelTask(task.getTaskId());
        }, 1L, 20L);

        taskRef.compareAndSet(null, bukkitTask);
    }

So könnte man den Timer sogar asynchron laufen lassen, aber 1) ist das für eine so kleine Aufgabe unnötig und 2) spart man sich damit das synchronisieren vom Messaging - Bukkit.broadcastMessage ist nicht thread-safe soweit ich mich erinnern kann.

Der Task cancelt sich selbstständig sobald er seine Aufgabe erfüllt hat.

Sorry, wenn das Beispiel ein bisschen overkill gehandhabt ist an manchen Stellen.
Mein aktuelles Projekt auf Arbeit zwingt mich dazu jede Kleinigkeit derartig zu handhaben - das färbt leicht ab.
 

MaxDerVerpeilte

Redstoneengineer
Registriert
30 Juni 2017
Beiträge
34
Alter
38
Diamanten
300
Hi! Nach längerem Forschen habe ich jetzt auch die Scheduler annähernd verstanden. Doch stellt sich mir jetzt das Problem, dass meine gute Scheduler nicht runter zählen will, da final eine "final" variable sein muss, doch wenn ich es zu einer mache funktioniert es immer noch nicht.

Code:
                            Integer c = Integer.parseInt(args[0]);
                            Integer u = Integer.parseInt(args[1]);
                            final int high =c;

u wird für die Switch verwendet und stellt den Abstand in Sekunden dar, hat also in diesem Fall keine besondere Bedeutung. Und ja ich weiß, dass ich U auch einfach in die scheduler einbauen könnte. c Steht für die Zahl von der der Countdown aus beginnt. Also wenn c=5 -> 5, 4, 3...

Code:
case 1:
                       
                       
                        Bukkit.getScheduler().scheduleSyncRepeatingTask(this.plugin, new Runnable(){

                            @Override
                            public void run() {
                            Bukkit.broadcastMessage(countdown.pr + " §6---§b " + final + " §6---");
                            final--;  
                            }
                        },20, 20*c);
                        Bukkit.broadcastMessage(countdown.pr + " §6---§b " + "GO!" + " §6---");
                          break;
 

FelixKlauke

Erzengel
Ehem. Teammitglied
Registriert
5 Januar 2014
Beiträge
1.038
Diamanten
299
Minecraft
FelixKlauke
Hi! Nach längerem Forschen habe ich jetzt auch die Scheduler annähernd verstanden. Doch stellt sich mir jetzt das Problem, dass meine gute Scheduler nicht runter zählen will, da final eine "final" variable sein muss, doch wenn ich es zu einer mache funktioniert es immer noch nicht.

Code:
                            Integer c = Integer.parseInt(args[0]);
                            Integer u = Integer.parseInt(args[1]);
                            final int high =c;

u wird für die Switch verwendet und stellt den Abstand in Sekunden dar, hat also in diesem Fall keine besondere Bedeutung. Und ja ich weiß, dass ich U auch einfach in die scheduler einbauen könnte. c Steht für die Zahl von der der Countdown aus beginnt. Also wenn c=5 -> 5, 4, 3...

Code:
case 1:
                     
                     
                        Bukkit.getScheduler().scheduleSyncRepeatingTask(this.plugin, new Runnable(){

                            @Override
                            public void run() {
                            Bukkit.broadcastMessage(countdown.pr + " §6---§b " + final + " §6---");
                            final--;
                            }
                        },20, 20*c);
                        Bukkit.broadcastMessage(countdown.pr + " §6---§b " + "GO!" + " §6---");
                          break;

Für dieses "final Problem" gibt es ein simples Workaround. Ganz simpel dargestellt:
Code:
List<String> list = new ArrayList<>();
      
final int[] i = {0};
      
list.forEach(element -> {
    i[0]++;
});

Das ist einfach ein Problem dass du mit einem array umgehen kannst. Vernünftige IDEs sollten dir eine solche Lösung jedoch bereits vorschlagen. Zumindest IntelliJ tut genau dies.
 
Oben