BT

Diffuser les Connaissances et l'Innovation dans le Développement Logiciel d'Entreprise

Contribuez

Sujets

Sélectionner votre région

Accueil InfoQ Actualités JEP 429 : Variables Extent-Local Pour Promouvoir L'Immuabilité En Java

JEP 429 : Variables Extent-Local Pour Promouvoir L'Immuabilité En Java

La JEP 429, Extent-Local Variables (Incubator), a été promue de son statut JEP Draft 8263012 à Candidate. Cette JEP en incubation, sous l'égide du projet Loom, propose de permettre le partage de données immuables dans et entre les threads. Ceci est préférable aux variables thread-local, en particulier lors de l'utilisation d'un grand nombre de threads virtuels.

Dans cette JEP, au lieu d'utiliser la classe ThreadLocal, un nouveau type, ExtentLocal, est proposé. Une variable extent-local permet aux données d'être partagées en toute sécurité entre les composants d'un grand programme. Habituellement, il est déclaré comme un champ statique final, il est donc facilement accessible à partir de nombreux composants. Il est écrit une seule fois, immuable et disponible uniquement pendant une période limitée lors de l'exécution du thread. Considérez l'exemple suivant :

class Server {
    final static ExtentLocal<Principal> PRINCIPAL = new ExtentLocal<>();

    void serve(Request request, Response response) {
        var level = (request.isAdmin() ? ADMIN : GUEST);
        var principal = new Principal(level);
        ExtentLocal.where(PRINCIPAL, principal)
                .run(() -> Application.handle(request, response));
    }
}

class DBAccess {
    DBConnection open() {
        var principal = Server.PRINCIPAL.get();
        if (!principal.canOpen()) throw new InvalidPrincipalException();
        return newConnection();
    }
}    

En règle générale, les grands programmes Java sont composés de plusieurs composants qui partagent des données. Par exemple, une infrastructure Web peut nécessiter des composants serveur et d'accès aux données. Les objets d'authentification et d'autorisation des utilisateurs doivent être partagés entre les composants. Le composant serveur peut créer l'objet puis le transmettre comme argument à l'invocation de la méthode. Cette méthode de transmission d'arguments n'est pas toujours viable car le composant serveur peut d'abord appeler un code utilisateur non approuvé. ThreadLocal représente une des alternatives disponibles. Prenons l'exemple suivant utilisant ThreadLocal :

class Server {
    final static ThreadLocal<Principal> PRINCIPAL = new ThreadLocal<>();

    public void serve(Request request, Response response) {
        var level = (request.isAuthorized() ? ADMIN : GUEST);
        var principal = new Principal(level);
        PRINCIPAL.set(principal);
        Application.handle(request, response);
    }
}

class DBAccess {
    DBConnection open() {
        var principal = Server.PRINCIPAL.get();
        if (!principal.canOpen()) throw new InvalidPrincipalException();
        return newConnection();
    }
}

Dans l'exemple ci-dessus, l'objet PRINCIPAL représente le ThreadLocal, instancié dans la classe Server, où les données sont initialement stockées. Ensuite, il est utilisé plus tard dans la classe DBAccess. En utilisant la variable ThreadLocal, nous évitons que le composant serveur appelle un PRINCIPAL comme argument de méthode lorsque le composant serveur appelle le code utilisateur, et le code utilisateur appelle le composant d'accès aux données.

Bien que cette approche semble convaincante, elle présente de nombreux défauts de conception impossibles à éviter :

Mutabilité sans contrainte : chaque variable thread-local est mutable. Cela signifie que les méthodes get() et set() d'une variable peuvent être appelées à tout moment. L'API ThreadLocal permet cette prise en charge. Un modèle de communication général dans lequel les données peuvent circuler dans les deux sens entre les composants conduit à un flux de données de type spaghetti.

Durée de vie illimitée : des fuites de mémoire peuvent se produire dans les programmes qui reposent sur la mutabilité illimitée des variables thread-local. Étant donné que les développeurs oublient souvent d'appeler remove(), les données par thread sont souvent conservées plus longtemps que nécessaire. Il serait préférable que l'écriture et la lecture des données par thread se produisent dans un laps de temps limité pendant l'exécution du thread, éliminant ainsi la possibilité de fuites.

Héritage coûteux : lors de l'utilisation d'un grand nombre de threads, la surcharge des variables thread-local peut augmenter car les threads enfants peuvent hériter des variables thread-local d'un thread parent. Cela peut ajouter une empreinte mémoire importante.

Avec la disponibilité des threads virtuels (JEP 425), les problèmes de variables thread-local sont devenus plus pressants. Plusieurs threads virtuels partagent les mêmes threads porteurs (carrier threads). Cela nous permet de créer un grand nombre de threads virtuels. Cela signifie qu'un framework Web peut donner à chaque requête son propre thread virtuel tout en traitant simultanément des milliers ou des millions de requêtes.

En bref, les variables thread-local ont plus de complexité que ce qui est généralement nécessaire pour partager des données et entraînent des coûts élevés qui ne peuvent être évités.

Cette JEP vise à résoudre tous ces problèmes avec ThreadLocal et à fournir de meilleures alternatives.

Les développeurs intéressés à discuter de cette nouvelle classe ExtentLocal peuvent visiter ce fil Reddit.

 

Au sujet de l’Auteur

Evaluer cet article

Pertinence
Style

Contenu Éducatif

BT