Lernen Sie Flyweight-Muster und ConcurrentHashMap in Java

Ich lese die dritte Ausgabe von Essential Java, um meine Java-Kenntnisse zu aktualisieren, und das Muster "Fliegengewicht" wird angezeigt. Übrigens habe ich dieses Muster nie richtig gemacht, also habe ich beschlossen, es zu verstehen und auszuprobieren.

Fliegengewichtsmuster

Das Flyweight-Muster ist eines der Entwurfsmuster von GoF und dient zur Lösung der folgenden Probleme.

Definition

Ich bin mir nicht sicher, ob das alles ist.

image.png

In der Sequenz sieht es aus wie ein Caching-Muster. Wenn Sie sich das Verlaufselement ansehen, scheint es, dass es im Dokumenteditor verwendet wurde. Wenn die Schriftinformationen, z. B. das Alphabet, 26 Zeichen umfassen und jedes Mal eine Instanz des Zeichens erstellt wird, wird eine große Anzahl von Instanzen generiert. Daher scheint es ein Mechanismus zu sein, nur 26 Instanzen zu erstellen und zwischenzuspeichern und zurückzugeben.

Klangbeispiel für Gitarrenbünde

Lassen Sie uns ein Beispiel machen und es verstehen. Kurz gesagt, es ist ein Factory-Cache, also ist es einfach. Dieses Mal ist das Motiv ein wenig Brute Force, aber es ist eine Anwendung, die den Klang dieses Ortes zurückgibt, wenn Sie die Saitennummer und die Bundnummer der Gitarre eingeben. Da es nur 12 Sounds gibt, sollten 12 Instanzen ausreichen. Versuchen Sie, "Sound" als "Flyweight" -Objekt im Entwurfsmusterdiagramm zu verwenden.

Sound.java : Flyweight

package com.company;

public interface Sound {
    void Play();
}

SoundImpl : Flywieght1

package com.company;

public class SoundImpl implements Sound{
    private String note;
    public SoundImpl(String note) {
        this.note = note;
    }
    @Override
    public void Play() {
        System.out.println(note + "- ♪");
    }
    public String getNote() {
        return note;
    }
}

SoundFactory : FlywieghtFactory

package com.company;

import java.util.HashMap;

public class SoundFactory {
    private static Map<String, Sound> sounds = new HashMap<String, Sound>();
    public static Sound getSound(String note) {
        if (sounds.containsKey(note)){
            return sounds.get(note);
        } else {
            Sound sound = new SoundImpl(note);
            sounds.put(note, sound);
            return sound;
        }
    }
}

Der Main schwoll an und war nicht cool, aber trotzdem bekam ich etwas, das funktionierte. Der einfache Punkt ist, Factory eine Karte zu geben und sie zwischenzuspeichern. Es ist einfach.

Main.java

package com.company;

import java.util.HashMap;

public class Main {
    private static HashMap<Integer, Integer> stringMap = new HashMap<Integer, Integer>();
    private static HashMap<Integer, String> notes = new HashMap<Integer, String>();
    private static void setup() {
        stringMap.put(1, 4);
        stringMap.put(2, 11);
        stringMap.put(3, 7);
        stringMap.put(4, 2);
        stringMap.put(5, 9);
        stringMap.put(6, 4);

        notes.put(0, "C");
        notes.put(1, "C#");
        notes.put(2, "D");
        notes.put(3, "D#");
        notes.put(4, "E");
        notes.put(5, "F");
        notes.put(6, "F#");
        notes.put(7, "G");
        notes.put(8, "G#");
        notes.put(9, "A");
        notes.put(10, "A#");
        notes.put(11, "B");

    }
    public static void main(String[] args) {
        setup();
	    while(true) {
	        java.io.Console con = System.console();
	        if (con != null) {
                String input = con.readLine("string:fret:");
                if (input.contains("exit")) {
                    System.out.println("Closing ...");
                    System.exit(0);
                } else {
                    String[] stringFret = input.split(":");
                    int openNote = stringMap.get(Integer.parseInt(stringFret[0]));
                    int fret = Integer.parseInt(stringFret[1]);
                    int note = openNote + fret;
                    if (note >= 12) {
                        note = note - 12;
                    }
                    String noteString =  notes.get(new Integer(note));
                    Sound sound = SoundFactory.getSound(noteString);
                    sound.Play();
                }
            }

        }
    }

}

Was passiert mit Concurrent?

Da der Hauptteil einfach war, bin ich mit Java nicht sehr vertraut, deshalb habe ich beschlossen, Schritte zu unternehmen. Was soll ich tun, wenn es sich in einem gleichzeitigen Zustand befindet? HashMap scheint nicht threadsicher zu sein. Wenn Sie Thread-sicher machen möchten, können Sie "HashTable" oder "ConcurrentHashMap" verwenden. Was ist der Unterschied?

HashTable und ConcurrentHashMap

Wenn man sich diese Vergleiche ansieht, scheint es viele Fälle zu geben, in denen es eindeutig angemessen ist, "ConcurrentHashMap" zu verwenden. Lassen Sie es uns implementieren.

Implementiert mit Micronaut

Klingt einfach.

Micronaut install

In meiner Umgebung wurde die Quelle von "schokoladig" neu geschrieben, daher werde ich die Standardeinstellung wiederherstellen. Es kann installiert werden, indem PowerShell mit Administratorrechten gestartet wird.

$ choco isntall micronaut -s https://chocolatey.org/api/v2/

Generate project via template

Sie können ein Maven-Projekt wie folgt generieren:

$ mn create-app flyweight-server --build maven

Zunächst wird dadurch der Server hochgefahren. Der Punkt, auf den ich süchtig war, war, dass ich den Code mit IntelliJ geschrieben habe, aber das Terminal JAVA_HOME nicht festgelegt wurde und die Fehlermeldung "Verursacht durch: java.lang.IllegalArgumentException: ungültige Zielversion: 11" angezeigt wurde. Es kam heraus. Ursprünglich befand sich nur das Java8-JDK im Pfad, das ist also ein Problem, aber ich erinnerte mich daran, dass die Grundlagen von Java darin bestehen, JAVA_HOME festzulegen und% JAVA_HOME% / bin im Pfad zu übergeben. Andernfalls funktioniert maven nicht richtig.

$ cd flywieght-server
$ mvn clean package
$ java -jar .\target\flyweight-server-0.1.jar

Controller hinzufügen

Ich werde den Controller hinzufügen. Micronaut scheint verschiedene Funktionen zu unterstützen, wie beispielsweise eine leichte Version von Spring. Ich wollte diesmal nur HTTP-Server, also schaue ich mir das Handbuch an und schreibe den Code. Um mit dem Controller zu regieren, müssen Sie anscheinend nur den Controller schreiben. Es ist sehr leicht.

*The HTTP Server

FlyweightController.java

package flyweight.server;

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

@Controller("/flyweight")
public class FlyweightController {
    @Get(value = "/{string}/{fret}", produces = MediaType.TEXT_PLAIN)
    public String index(Integer string, Integer fret){
        return "String: " + string + " Fret: "+ fret;
    }
}

Jetzt, wo es funktioniert, verstehe ich, was der Controller wissen möchte. Als nächstes ändern wir die Flyweight-App. Ich denke, das funktioniert in mehreren Threads. Verwenden wir also die zuvor erwähnte "ConcurrentHashMap".

Wie kürzer es war als zuvor. Die Methode "computeIfAbsent" akzeptiert jetzt Funktionen und garantiert atomares Verhalten. Dies ist die gleiche Atmosphäre wie beim C # ConcurrentDictionary. Wenn es also nicht existiert, erstellt es ein neues und gibt es zurück, andernfalls gibt es das vorhandene zurück. Das beste!

SoundFactory.java

package flyweight.server;

import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class SoundFactory {
    private static ConcurrentMap<String, Sound> sounds = new ConcurrentHashMap<String, Sound>();
    public static Sound getSound(String note) {
        return sounds.computeIfAbsent(note, n -> new SoundImpl(n));
    }
}

Gesamtbild

FlyweightController.java

package flyweight.server;

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

@Controller("/flyweight")
public class FlyweightController {
    @Get(value = "/{string}/{fret}", produces = MediaType.TEXT_PLAIN)
    public String index(Integer string, Integer fret){
        Integer openNote = Constants.stringMap.get(string.intValue());
        int note = openNote.intValue() + fret.intValue();
        if (note >= 12) {
            note = note - 12;
        }
        Sound sound = SoundFactory.getSound(Constants.notes.get(note));
        return "String: " + string + " Fret: "+ fret + " Sound: " + sound.Play();
    }
}

Constants.java

package flyweight.server;

import java.util.HashMap;

public class Constants {
    static HashMap<Integer, Integer> stringMap = new HashMap<Integer, Integer>();
    static HashMap<Integer, String> notes = new HashMap<Integer, String>();
    static void setup() {
        stringMap.put(1, 4);
        stringMap.put(2, 11);
        stringMap.put(3, 7);
        stringMap.put(4, 2);
        stringMap.put(5, 9);
        stringMap.put(6, 4);

        notes.put(0, "C");
        notes.put(1, "C#");
        notes.put(2, "D");
        notes.put(3, "D#");
        notes.put(4, "E");
        notes.put(5, "F");
        notes.put(6, "F#");
        notes.put(7, "G");
        notes.put(8, "G#");
        notes.put(9, "A");
        notes.put(10, "A#");
        notes.put(11, "B");

    }
}

Sound.java

package flyweight.server;

public interface Sound {
    String Play();
}

SoundImpl.java

package flyweight.server;

public class SoundImpl implements Sound {
    private String note;

    public SoundImpl(String note) {
        this.note = note;
    }

    public String Play() {
        return this.note + "- note";
    }

    public String getNote() {
        return this.note;
    }
}

Application.java

package flyweight.server;

import io.micronaut.runtime.Micronaut;

public class Application {

    public static void main(String[] args) {
        Constants.setup();
        Micronaut.run(Application.class, args);
    }
}

Ausführungsergebnis

[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing C:\Users\tsushi\Code\java\spike\micronaut\flyweight-server\target\flyweight-server-0.1.jar with C:\Users\tsushi\Code\java\spike\micronaut\flyweight-server\target\flyweight-server-0.1-shaded.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.444 s
[INFO] Finished at: 2020-10-26T14:16:48-07:00
[INFO] ------------------------------------------------------------------------
PS C:\Users\tsushi\Code\java\spike\micronaut\flyweight-server> java -jar .\target\flyweight-server-0.1.jar
←[36m14:17:24.022←[0;39m ←[1;30m[main]←[0;39m ←[34mINFO ←[0;39m ←[35mio.micronaut.runtime.Micronaut←[0;39m - Startup completed in 1154ms. Server Running: http://localhost:8080

image.png

Ich bin froh, dass ich heute das "Flyweight" -Muster und die "ConcurrentHashMap" leicht gelernt habe.

Resource

Recommended Posts

Lernen Sie Flyweight-Muster und ConcurrentHashMap in Java
Beispiel für Codierung und Decodierung in Java
Wie man JAVA in 7 Tagen lernt
StringBuffer- und StringBuilder-Klasse in Java
Verstehe gleich und hashCode in Java
Hallo Welt in Java und Gradle
Java Dekon'nichiwa Welt (Tsu lernen schnell Grammatik in Vim und Quickrun)
Unterschied zwischen final und Immutable in Java
Programmieren Sie PDF-Kopf- und Fußzeilen in Java
Die Richtung von Java in "C ++ Design and Evolution"
Von Java nach C und von C nach Java in Android Studio
Lesen und Schreiben von GZIP-Dateien in Java
Unterschied zwischen int und Integer in Java
Diskriminierung von Enum in Java 7 und höher
In Bezug auf transiente Modifikatoren und Serialisierung in Java
Erkennen Sie ähnliche Videos in Java und OpenCV Version 2
Partisierung in Java
Unterschied zwischen next () und nextLine () in Java Scanner
Änderungen in Java 11
Janken in Java
Java-Entwurfsmuster
Erkennen Sie ähnliche Videos in Java und OpenCV Version 3
Weitere Informationen zu Sammlungen und Mitgliedern finden Sie in route.rb
Hinzufügen, Lesen und Löschen von Excel-Kommentaren mit Java
Überprüfen Sie das statische und öffentliche Verhalten in Java-Methoden
[Java] Verstehe in 10 Minuten! Assoziatives Array und HashMap
Java und JavaScript
XXE und Java
Unterscheiden Sie in Java zwischen positiven und negativen Zahlen
Java fügt Wasserzeichen in Word-Dokumenten hinzu und entfernt sie
Erkennen Sie ähnliche Videos in Java und OpenCV Version 1
Umfangsrate in Java
Repräsentiert "nächster Tag" und "vorheriger Tag" in Java / Android
Fragen in Java-Ausnahmebehandlung werfen und versuchen-fangen
Laden Sie Notizen in Java auf S3 hoch und laden Sie sie herunter
Verschlüsseln / Entschlüsseln mit AES256 in PHP und Java
Generieren Sie OffsetDateTime aus Clock und LocalDateTime in Java
FizzBuzz in Java
Konvertieren Sie JSON und YAML in Java (mit Jackson und SnakeYAML)
Versuchte Mastodons Toot- und Streaming-API in Java
Schreiben Sie ABNF in Java und geben Sie die E-Mail-Adresse weiter
Vektorisieren und bildgeben Sie handgeschriebene numerische MNIST-Bilddaten mit Java
[Java] Unterschied zwischen statischem final und final in Mitgliedsvariablen
Zum ersten Mal lernen Java # 3 Ausdrücke und Operatoren
In der Abbildung verstandene Java-Klassen und -Instanzen
Java-Join- und Split-Tabellenzellen im Word-Dokument
Dies und das zum Bearbeiten von ini in Java. : inieditor-java
So konvertieren Sie A in a und a in A mit logischem Produkt und Summe in Java
Subtrahieren Sie Enum-Konstanten von Zeichenfolgen und Werten in Java zurück
~ Ich habe jetzt versucht, funktionale Programmierung mit Java zu lernen ~
Lesen Sie JSON in Java
Interpreter-Implementierung durch Java
Janken App in Java
Einschränkungsprogrammierung in Java
Setzen Sie Java8 in Centos7
NVL-artiger Typ in Java
Verbinden Sie Arrays in Java