ThreadLocal は、スレッドのライフ サイクル全体でいつでもアクセスできるスレッド固有のオブジェクトを提供します。これにより、一部のロジックの実装が大幅に容易になります。
ThreadLocal には主に 2 つの一般的な使用法があります:
複数レベルのパラメータの受け渡しを避けるためにスレッド コンテキスト オブジェクトを保存します。
複数のスレッドからの同時呼び出しを避けるために、スレッドセーフでないオブジェクトを保存します。
ここでは、PageHelper プラグのソース コードでページング パラメーターの設定と使用を取得します。例として -in。
ページング パラメータ コードの設定:
/** 分页方法类 */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; } }
ページング パラメータ コードの使用:
/** 虚辅助方言类 */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); } ... }
ページング プラグイン コードの使用:
/** 查询用户函数 */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; }
ページングを渡したい場合パラメータから関数パラメータまで クエリステートメントを段階的に渡すことは、MyBatis 関連のインターフェイス関数が変更されない限り不可能です。
日付フォーマット ツール関数を作成するとき、最初に思い浮かぶのは次のようなことです:
/** 日期模式 */private static final String DATE_PATTERN = "yyyy-MM-dd";/** 格式化日期函数 */public static String formatDate(Date date) { return new SimpleDateFormat(DATE_PATTERN).format(date); }
このうち、DateFormat は呼び出しごとに初期化する必要があり、パフォーマンスが低下するため、DateFormat を定数として定義した後の書き方は次のようになります:
/** 日期格式 */private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");/** 格式化日期函数 */public static String formatDate(Date date) { return DATE_FORMAT.format(date); }
SimpleDateFormat はスレッドセーフではないため、複数のスレッドが同時に formatDate 関数を呼び出すと、返される結果は予期したものと異なります。 ThreadLocal を使用してスレッド固有のオブジェクトを定義する場合、最適化されたコードは次のとおりです。
/** 本地日期格式 */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); }
これは、スレッドセーフな日付書式設定ツール クラスが存在する前の実装メソッドです。 JDK8 以降では、SimpleDateFormat の代わりに DateTimeFormatter を使用することをお勧めします。これは、SimpleDateFormat はスレッド セーフではありませんが、DateTimeFormatter はスレッド セーフであるためです。もちろん、Apache の DateFormatUtils ツール クラスなど、サードパーティが提供するスレッドセーフな日付書式設定関数を使用することもできます。
注: ThreadLocal にはメモリ リークのリスクがあるため、ビジネス コードが終了する前に削除関数を呼び出してデータをクリアするようにしてください。
以上がJava が ThreadLocal を使用してスレッド固有のオブジェクトを保存する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。