Asynchrone Operationen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

Registriere dich um viele Vorteile zu genießen! Weniger Werbung, bessere Kommunikation und vieles mehr!

  • Ein kurzes Beispiel für Asynchrone IO Operationen
    Hey,

    es kommt immer wieder zu Missverständnissen beim Thema "Asynchrone Datenbankabfragen und sonstige IO Operationen". Rückgabewerte, Callbacks und der Ablauf werden fehlinterpretiert, falsch interpretiert - Aber auch nirgendwo richtig erklärt. Hier möchte ich mich kurz dazu äußern.

    Unser Ziel: Ein Einhorn. Wir bauen uns ein Einhorn um dieses dann zu reiten. Das Einhorn sieht so aus:
    Spoiler anzeigen

    Java-Quellcode

    1. private class Unicorn {
    2. public void ride(){
    3. //Piiiiink fluffy Unicorns...
    4. }
    5. }








    Dieses Einhorn braucht eine Weile um heranzureifen. Wir gehen hier bei einer Instanziierung von 2 Sekunden aus (Der Code hier gibt das nicht her!!). Wir haben eine Klasse AsyncExample mit der wir unser Einhorn laden können. Diese enthält eine synchrone und eine asynchrone Methode.

    Die synchrone Methode ist relativ einfach und deshalb kommt sie zuerst:
    Spoiler anzeigen

    Java-Quellcode

    1. package de.nathalieoneill.io;
    2. import java.util.concurrent.Executor;
    3. import java.util.concurrent.Executors;
    4. public class AsyncExample {
    5. /**
    6. * This method represents a very very long query. It could take about 2secs to be finished.
    7. * That could be a http GET Request or several Database Operations.
    8. */
    9. public Unicorn doLongQuery(){
    10. //Do some really cool stuff, like registering a Unicorn or riding a horse.
    11. //You could dance or listen to music, just try to do something that will take a wile.
    12. return new Unicorn();
    13. }
    14. private static class Unicorn {
    15. public void ride(){
    16. //Piiiiink fluffy Unicorns...
    17. }
    18. }
    19. }
    Alles anzeigen


    Mit AsnycExample#doLongQuery() bekommen wir nun direkt unser geliebtes rosa Plüscheinhorn. Dauert allerdings ein wenig und der Main Thread friert ein:
    Spoiler anzeigen

    Java-Quellcode

    1. package de.nathalieoneill.io;
    2. import java.util.concurrent.Executor;
    3. import java.util.concurrent.Executors;
    4. public class AsyncExample {
    5. /**
    6. * This will execute the long query in a sync way in the main thread
    7. */
    8. public Unicorn doSync(){
    9. Unicorn unicorn = doLongQuery();
    10. return unicorn;
    11. }
    12. /**
    13. * This method represents a very very long query. It could take about 2secs to be finished.
    14. * That could be a http GET Request or several Database Operations.
    15. */
    16. public Unicorn doLongQuery(){
    17. //Do some really cool stuff, like registering a Unicorn or riding a horse.
    18. //You could dance or listen to music, just try to do something that will take a wile.
    19. return new Unicorn();
    20. }
    21. public static void main(String[] args) {
    22. AsyncExample example = new AsyncExample();
    23. //First we use the evil way
    24. // We call this the time t
    25. Unicorn unicorn = example.doSync();
    26. unicorn.ride();
    27. // Now we have the time [ t + 2s ]
    28. //With this we blocked our main thread for seconds ;( Not cool - CRY IN PAIN!
    29. }
    30. private static class Unicorn {
    31. public void ride(){
    32. //Piiiiink fluffy Unicorns...
    33. }
    34. }
    35. }
    Alles anzeigen


    In kurz, das ist böse. Wir werden nun unsere Herangehensweise ändern und unser Einhorn asynchron erzeugen und reiten. Dafür brauchen wir ein sogenanntes Callback:
    Spoiler anzeigen

    Java-Quellcode

    1. private interface Callback<T> {
    2. void run(T result);
    3. }


    Wir führen auch eine neue Methode ein: AsyncExample#doAsync() Diese hat allerdings keinen Rückgabewert mehr und erfordert sogar ein Callback als Parameter!

    Ihr könnt euch das wie ein Einhorn vorstellen, das etwas trinken muss aber auch durch die große Weite Welt läuft. Es gibt in der Fantasiewelt mit Einhörnern eine Regenwolke. Diese bewegt sich jedoch nicht und bleibt die ganze Zeit an der gleichen Stelle und spendet Trinkwasser. Das Einhorn muss stehen bleiben um zu trinken und ist "blockiert". Wenn die Wolke aber neben dem Einhorn her fliegt, kann es unterwegs trinken.
    Das Einhorn ist Unser Programm, das Trinkwasser das Ergebnis eines langen Queries und die Wolke eine Datenbank.

    Das Callback bekommt mit auf den Weg was es mit dem Ergebnis machen soll (Zb das Einhorn mit Wasser versorgen). Das sieht so aus:

    Spoiler anzeigen

    Java-Quellcode

    1. package de.nathalieoneill.io;
    2. import java.util.concurrent.Executor;
    3. import java.util.concurrent.Executors;
    4. public class AsyncExample {
    5. private final Executor executor;
    6. public AsyncExample(){
    7. executor = Executors.newCachedThreadPool();
    8. }
    9. /**
    10. *
    11. * @param unicornCallback the callback the unicorn will be given too when the long query is done
    12. */
    13. public void doAsync(final Callback<Unicorn> unicornCallback){
    14. this.executor.execute(new Runnable() {
    15. public void run() {
    16. Unicorn unicorn = doLongQuery();
    17. unicornCallback.run(unicorn);
    18. }
    19. });
    20. }
    21. /**
    22. * This method represents a very very long query. It could take about 2secs to be finished.
    23. * That could be a http GET Request or several Database Operations.
    24. */
    25. public Unicorn doLongQuery(){
    26. //Do some really cool stuff, like registering a Unicorn or riding a horse.
    27. //You could dance or listen to music, just try to do something that will take a wile.
    28. return new Unicorn();
    29. }
    30. public static void main(String[] args) {
    31. AsyncExample example = new AsyncExample();
    32. example.doAsync(new Callback<Unicorn>() {
    33. public void run(Unicorn unicorn) {
    34. //We have our Unicorn!!!!! <3
    35. unicorn.ride();
    36. // Now we have the time [ t + 2s ]
    37. }
    38. });
    39. // Now we have the time [ t + ~1ms ]
    40. // ACHIEVEMENT! Not interrupted the fancy program flow, I FEEEEEL THE FLOOOOOOWWWWWWWW
    41. }
    42. private interface Callback<T> {
    43. void run(T result);
    44. }
    45. private static class Unicorn {
    46. public void ride(){
    47. //Piiiiink fluffy Unicorns...
    48. }
    49. }
    50. }
    Alles anzeigen


    Der Programmfluss wird dadurch nicht unterbrochen und das Einhorn kann man trotzdem reiten, sobald es geladen ist. Das müsst ihr allerdings selbstständig auf z.B. MySQL übertragen, ich habe euch nur ein kleines Modell gegeben.

    Hier nochmal als ganze Klasse mit allem drin:

    Spoiler anzeigen

    Java-Quellcode

    1. package de.nathalieoneill.io;
    2. import java.util.concurrent.Executor;
    3. import java.util.concurrent.Executors;
    4. public class AsyncExample {
    5. private final Executor executor;
    6. public AsyncExample(){
    7. executor = Executors.newCachedThreadPool();
    8. }
    9. /**
    10. * This will execute the long query in a sync way in the main thread
    11. */
    12. public Unicorn doSync(){
    13. Unicorn unicorn = doLongQuery();
    14. return unicorn;
    15. }
    16. /**
    17. *
    18. * @param unicornCallback the callback the unicorn will be given too when the long query is done
    19. */
    20. public void doAsync(final Callback<Unicorn> unicornCallback){
    21. this.executor.execute(new Runnable() {
    22. public void run() {
    23. Unicorn unicorn = doLongQuery();
    24. unicornCallback.run(unicorn);
    25. }
    26. });
    27. }
    28. /**
    29. * This method represents a very very long query. It could take about 2secs to be finished.
    30. * That could be a http GET Request or several Database Operations.
    31. */
    32. public Unicorn doLongQuery(){
    33. //Do some really cool stuff, like registering a Unicorn or riding a horse.
    34. //You could dance or listen to music, just try to do something that will take a wile.
    35. return new Unicorn();
    36. }
    37. // ----------------- [ IMPORTANT! ] -----------------
    38. // ----------------- [ IMPORTANT! ] -----------------
    39. // ----------------- [ IMPORTANT! ] -----------------
    40. public static void main(String[] args) {
    41. AsyncExample example = new AsyncExample();
    42. //First we use the evil way
    43. // We call this the time t
    44. Unicorn unicorn = example.doSync();
    45. unicorn.ride();
    46. // Now we have the time [ t + 2s ]
    47. //With this we blocked our main thread for seconds ;( Not cool - CRY IN PAIN!
    48. //--------------------------------------------------------------------------
    49. //Now we will do it in the cool way, with flowers, choco and some cookies <3
    50. // We call this the time t
    51. example.doAsync(new Callback<Unicorn>() {
    52. public void run(Unicorn unicorn) {
    53. //We have our Unicorn!!!!! <3
    54. unicorn.ride();
    55. // Now we have the time [ t + 2s ]
    56. }
    57. });
    58. // Now we have the time [ t + ~1ms ]
    59. // ACHIEVEMENT! Not interrupted the fancy program flow, I FEEEEEL THE FLOOOOOOWWWWWWWW
    60. }
    61. // ----------------- [ IMPORTANT! ] -----------------
    62. // ----------------- [ IMPORTANT! ] -----------------
    63. // ----------------- [ IMPORTANT! ] -----------------
    64. private interface Callback<T> {
    65. void run(T result);
    66. }
    67. private static class Unicorn {
    68. public void ride(){
    69. //Piiiiink fluffy Unicorns...
    70. }
    71. }
    72. }
    Alles anzeigen


    Viel Spaß damit!

    MFG
    Nathalie

    606 mal gelesen

Kommentare 4

  • KingSarkasmus -

    Aus irgendwelchen Gründen habe ich jetzt total Lust ein pinkes Einhorn zu reiten.....
    Ich find die Comments dazwischen Klasse ^^
    Zitat von Loki aus dem ersten Avengers: NICE!!!! ;)

  • leNic -

    Schönes Tutorial! Ohne die Kommentare in den Methoden, würde das ganze aber vielleicht noch etwas übersichtlicher sein :)

  • Encotric -

    Anstatt des eigenes Interfaces könntest du für Java 8 Nutzer eventuell noch das Consumer Interface erwähnen. Das tut exakt das gleiche wie dein Interface :)

    • Morgana Pendragon -

      Hey,

      der Eintrag ist absichtlich für Java 7 ausgelegt. Viele Gameserver bei diversen Hostern haben noch kein java 8 und auch zum Verständnis eignet sich eine selbst implementierte Version besser.