Threads Rückgabewert in Asynchronen Schedulers

Hey,
gibt es eine Möglichkeit, in einem Asynchronen Scheduler etwas zurück zu geben?
Brauche das ganze weil ich eine Website einlesen möchte, und dieses Asynchron geschehen muss, weil sonst der Main Thread einfriert. :/

Mein aktueller Code ist:
Java:
package de.Summerfeeling.CraftingBans;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import com.google.gson.JsonParser;

public class UUIDHandler {

	private static Map<String, UUID> cache = new HashMap<>();
	
	public static UUID getUUID(String player) {
		try{
			//Cache
			if(cache.containsKey(player)) return cache.get(player);
			//Einlesen
			BufferedReader reader = new BufferedReader(new InputStreamReader(new URL("https://api.mojang.com/users/profiles/minecraft/" + player).openConnection().getInputStream()));
			String uuid = new JsonParser().parse(reader.readLine()).getAsJsonObject().get("id").toString();
			return UUID.fromString(uuid);
		}catch(Exception e) {
			return null;
		}
	}
	
}

Jedoch würde so der Server (es ist für einen Minecraft-Server) für einen kurzen Moment einfrieren.
Weiß dort jemand eine Lösung?

Mit freundlichen Grüßen,
Summerfeeling/Timo
 

Thallius

Top Contributor
Du kannst z.B. dem zweitern Thread eine Referenz vom aufrufenden Thread im Konstruktor geben. Dann kann der zweite Thread, wenn er fertig ist, alles beliebige im aufrufenden Thread benutzen.

Gruß

Claus
 

arilou

Bekanntes Mitglied
Der asynchrone Prozess sollte, wenn er ein Ergebnis abzuliefern hat, es dem Empfänger "in den Briefkasten werfen" (beim Empfänger an eine Warteschlange (ArrayList) anhängen). Man nehme etwas Thread-sicheres, oder synchronisiere das "Einwerfen" selber.
Der "Empfänger" kann dann seine "Posteingänge" verarbeiten, wenn er Zeit dazu hat ~ der Benutzer kein "einfrieren" bemerken wird.
 
Der asynchrone Prozess sollte, wenn er ein Ergebnis abzuliefern hat, es dem Empfänger "in den Briefkasten werfen" (beim Empfänger an eine Warteschlange (ArrayList) anhängen). Man nehme etwas Thread-sicheres, oder synchronisiere das "Einwerfen" selber.
Der "Empfänger" kann dann seine "Posteingänge" verarbeiten, wenn er Zeit dazu hat ~ der Benutzer kein "einfrieren" bemerken wird.
Könntest du mir das vielleicht mal etwas genauer erklären?
 

arilou

Bekanntes Mitglied
Deine .getUUID(...) packst du in einen Thread; diesem machst du auch das "Hauptprogramm"(objekt) bekannt.
Java:
public class MyUuidSearcher extends Thread
{
  private MyMainProgram main ;
  private String player ;

  public MyUuidSearcher( MyMainProgram _main, String _player ) {
    main = _main;
    player = _player ;
  }

  public void run()
  {
    UUID result ;

    result = getUUID( player );
    main.addUUID( result );
  }
}
Und in der Hauptklasse gibt's:
Java:
public class MyMainProgram {
  private ArrayList<UUID> meinBriefkasten ;

  public MyMainProgram() {
    meinBriefkasten = new ArrayList<UUID> () ;
  }

  public synchronized void addUUID( UUID anID ) {
    meinBriefkasten.add( anID );
  }

  private synchronized UUID getFirstUUID() {
    UUID result = meinBriefkasten.firstElement() ;
    meinBriefkasten.removeElementAt( 0 );
    return result ;
  }

  // ...
Jetzt kann die .main für jede Anfrage einen MyUuidSearcher-Thread erstellen und starten, der dann nebenläufig seine Abfrage bearbeitet. Währenddessen rechnet .main was auch immer, und schaut gelegentlich nach, ob meinBriefkasten.size() > 0 ist, und falls ja, holt sie sich .getFirstUUID() raus und hantiert damit, wie's ihr beliebt.
 
Deine .getUUID(...) packst du in einen Thread; diesem machst du auch das "Hauptprogramm"(objekt) bekannt.
Java:
public class MyUuidSearcher extends Thread
{
  private MyMainProgram main ;
  private String player ;

  public MyUuidSearcher( MyMainProgram _main, String _player ) {
    main = _main;
    player = _player ;
  }

  public void run()
  {
    UUID result ;

    result = getUUID( player );
    main.addUUID( result );
  }
}
Und in der Hauptklasse gibt's:
Java:
public class MyMainProgram {
  private ArrayList<UUID> meinBriefkasten ;

  public MyMainProgram() {
    meinBriefkasten = new ArrayList<UUID> () ;
  }

  public synchronized void addUUID( UUID anID ) {
    meinBriefkasten.add( anID );
  }

  private synchronized UUID getFirstUUID() {
    UUID result = meinBriefkasten.firstElement() ;
    meinBriefkasten.removeElementAt( 0 );
    return result ;
  }

  // ...
Jetzt kann die .main für jede Anfrage einen MyUuidSearcher-Thread erstellen und starten, der dann nebenläufig seine Abfrage bearbeitet. Währenddessen rechnet .main was auch immer, und schaut gelegentlich nach, ob meinBriefkasten.size() > 0 ist, und falls ja, holt sie sich .getFirstUUID() raus und hantiert damit, wie's ihr beliebt.

Hey,
danke für die Antwort.
Jedoch gibt es bei mir keine .firstElement() und keine .removeElementAt(); Methode.
Mein aktueller Code ist:
Code:
package de.Summerfeeling.MyRealms.UUID;

import java.util.ArrayList;
import java.util.UUID;

public class UUIDHandler {

	private ArrayList<UUID> cache = new ArrayList<UUID>();
	
	public synchronized void addUUID(UUID uuid) {
		this.cache.add(uuid);
	}
	
	private synchronized UUID getFirstUUID() {
		UUID result = this.cache.get(0);
		this.cache.remove(0);
		return result;
	}
	
	public static void main(String[] args) {
		UUIDHandler handler = new UUIDHandler();
		Searcher searcher = new Searcher("Summerfeeling", handler);
		searcher.start();
		System.out.println(handler.getFirstUUID().toString());
	}
	
}
Und
Code:
package de.Summerfeeling.MyRealms.UUID;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.UUID;

import org.bukkit.craftbukkit.libs.com.google.gson.JsonParser;

public class Searcher extends Thread {
	
	private String player;
	private UUIDHandler handler;
	
	public Searcher(String player, UUIDHandler handler) {
		this.player = player;
		this.handler = handler;
	}
	
	public void run() {
		UUID result;
		result = getUUID(player);
		handler.addUUID(result);
	}
	
	private UUID getUUID(String player) {
		try{
			BufferedReader reader = new BufferedReader(new InputStreamReader(new URL("https://api.mojang.com/users/profiles/minecraft/" + player).openConnection().getInputStream()));
			String uuid = new JsonParser().parse(reader.readLine()).getAsJsonObject().get("id").toString();
			return UUID.fromString(uuid);
		}catch(Exception e) {
			return null;
		}
	}
 
	
}
und dabei wird mir folgende Excpetion geworfen:
Code:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
	at java.util.ArrayList.rangeCheck(ArrayList.java:635)
	at java.util.ArrayList.get(ArrayList.java:411)
	at de.Summerfeeling.MyRealms.UUID.UUIDHandler.getFirstUUID(UUIDHandler.java:15)
	at de.Summerfeeling.MyRealms.UUID.UUIDHandler.main(UUIDHandler.java:24)
So langsam verzweifel ich... wieso ist es so schwer, asynchron etwas abzurufen und es synchron zu verarbeiten? :(
 

arilou

Bekanntes Mitglied
Steht doch in der Exception:
Index: 0, Size: 0
Du versuchst, das erste Element (mit Index=0) aus der Liste zu lesen; diese enthält aber 0 Elemente (Size: 0) - und somit gibt es kein Element an Stelle 0...
Das kommt, weil du zwar deinen searcher .start()est, aber dann nicht darauf wartest, bis er sein Element eingelesen hat. Bevor du mittels handler.getFirstUUID() eine UUID "aus dem Briefkasten" entnehmen/verarbeiten kannst, musst du erst prüfen, ob denn im Handler(-"Briefkasten") überhaupt eine drin ist...


An Haltestelle A steigen 2 Leute in den Bus, an Haltestelle B steigen 5 Leute aus; an Haltestelle C müssen jetzt 3 Leute einsteigen, damit der Bus leer ist...
 
Zuletzt bearbeitet:

Ähnliche Java Themen

Neue Themen


Oben