Maison  >  Article  >  Java  >  Comment Java utilise ThreadLocal pour stocker des objets spécifiques au thread

Comment Java utilise ThreadLocal pour stocker des objets spécifiques au thread

WBOY
WBOYavant
2023-06-03 09:32:081459parcourir

Utilisez ThreadLocal pour stocker des objets spécifiques au thread

ThreadLocal fournit des objets spécifiques au thread accessibles à tout moment tout au long du cycle de vie du thread, ce qui facilite grandement la mise en œuvre d'une certaine logique.

Il existe deux principales utilisations courantes de ThreadLocal :

  1. Enregistrez l'objet de contexte de fil pour éviter le passage de paramètres à plusieurs niveaux

     ; #🎜 🎜#
  2. Enregistrez les objets non thread-safe pour éviter les appels simultanés de plusieurs threads.

1. Enregistrez l'objet de contexte de fil de discussion et évitez le passage de paramètres à plusieurs niveaux

Ici, les paramètres de pagination dans le code source du Le plug-in PageHelper est identique à Utiliser un exemple pour illustrer.

Définir le code du paramètre de pagination :

/** 分页方法类 */public abstract class PageMethod {    /** 本地分页 */
    protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();    /** 设置分页参数 */
    protected static void setLocalPage(Page page) {
        LOCAL_PAGE.set(page);
    }    /** 获取分页参数 */
    public static <T> Page<T> getLocalPage() {        return LOCAL_PAGE.get();
    }    /** 开始分页 */
    public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
        Page<E> page = new Page<E>(pageNum, pageSize, count);
        page.setReasonable(reasonable);
        page.setPageSizeZero(pageSizeZero);
        Page<E> oldPage = getLocalPage();        if (oldPage != null && oldPage.isOrderByOnly()) {
            page.setOrderBy(oldPage.getOrderBy());
        }
        setLocalPage(page);        return page;
    }
}
Utiliser le code du paramètre de pagination :

/** 虚辅助方言类 */public abstract class AbstractHelperDialect extends AbstractDialect implements Constant {    /** 获取本地分页 */
    public <T> Page<T> getLocalPage() {        return PageHelper.getLocalPage();
    }    /** 获取分页SQL */
    @Override
    public String getPageSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, CacheKey pageKey) {
        String sql = boundSql.getSql();
        Page page = getLocalPage();
        String orderBy = page.getOrderBy();        if (StringUtil.isNotEmpty(orderBy)) {
            pageKey.update(orderBy);
            sql = OrderByParser.converToOrderBySql(sql, orderBy);
        }        if (page.isOrderByOnly()) {            return sql;
        }        return getPageSql(sql, page, pageKey);
    }
    ...
}
Utiliser le code du plug-in de pagination :

/** 查询用户函数 */public PageInfo<UserDO> queryUser(UserQuery userQuery, int pageNum, int pageSize) {
    PageHelper.startPage(pageNum, pageSize);
    List<UserDO> userList = userDAO.queryUser(userQuery);
    PageInfo<UserDO> pageInfo = new PageInfo<>(userList);    return pageInfo;
}
#🎜 🎜# Si vous souhaitez transmettre les paramètres de pagination à l'instruction de requête étape par étape via les paramètres de fonction, il est impossible d'y parvenir à moins de modifier les fonctions d'interface liées à MyBatis.

2. Enregistrez les objets non thread-safe et évitez les appels simultanés de plusieurs threads

Lors de l'écriture d'une fonction d'outil de formatage de date, la première chose qui me vient à l'esprit est la suivante :

/** 日期模式 */private static final String DATE_PATTERN = "yyyy-MM-dd";/** 格式化日期函数 */public static String formatDate(Date date) {    return new SimpleDateFormat(DATE_PATTERN).format(date);
}
# 🎜🎜# Parmi eux, DateFormat doit être initialisé à chaque fois qu'il est appelé, ce qui entraîne de faibles performances. Après avoir défini DateFormat comme constante, il s'écrit comme suit :

/** 日期格式 */private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");/** 格式化日期函数 */public static String formatDate(Date date) {    return DATE_FORMAT.format(date);
}
. Étant donné que SimpleDateFormat n'est pas thread-safe, lorsque plusieurs threads appellent la fonction formatDate en même temps, les résultats renvoyés seront incohérents avec les attentes. Si ThreadLocal est utilisé pour définir des objets spécifiques au thread, le code optimisé est le suivant :

/** 本地日期格式 */private static final ThreadLocal<DateFormat> LOCAL_DATE_FORMAT = new ThreadLocal<DateFormat>() {    @Override
    protected DateFormat initialValue() {        return new SimpleDateFormat("yyyy-MM-dd");
    }
};/** 格式化日期函数 */public static String formatDate(Date date) {    return LOCAL_DATE_FORMAT.get().format(date);
}
Il s'agit de la méthode d'implémentation avant qu'il n'y ait une classe d'outil de formatage de date thread-safe. Après JDK8, il est recommandé d'utiliser DateTimeFormatter au lieu de SimpleDateFormat, car SimpleDateFormat n'est pas sécurisé pour les threads, tandis que DateTimeFormatter est sécurisé pour les threads. Bien entendu, vous pouvez également utiliser des fonctions de formatage de date thread-safe fournies par des tiers, telles que la classe d'outils DateFormatUtils d'Apache.

Remarque : ThreadLocal présente un certain risque de fuite de mémoire. Essayez d'appeler la fonction de suppression pour effacer les données avant la fin du code métier.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer