>  기사  >  Java  >  Java가 ThreadLocal을 사용하여 스레드별 객체를 저장하는 방법

Java가 ThreadLocal을 사용하여 스레드별 객체를 저장하는 방법

WBOY
WBOY앞으로
2023-06-03 09:32:081446검색

ThreadLocal을 사용하여 스레드별 개체 저장

ThreadLocal은 스레드 수명 주기 전체에서 언제든지 액세스할 수 있는 스레드별 개체를 제공하므로 일부 논리 구현을 크게 촉진합니다.

ThreadLocal에는 두 가지 주요 일반적인 사용법이 있습니다.

  1. 다중 수준 매개변수 전달을 방지하기 위해 스레드 컨텍스트 객체를 저장합니다.

  2. 다중 스레드 동시 호출을 방지하기 위해 스레드로부터 안전하지 않은 객체를 저장합니다.

1. 다중 레벨 매개변수 전달을 방지하기 위해 스레드 컨텍스트 개체를 저장합니다.

여기서 PageHelper 플러그인 소스 코드의 페이징 매개변수 설정 및 사용을 예로 들어 보겠습니다.

페이징 매개변수 코드 설정:

/** 分页方法类 */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 관련 인터페이스 기능. 그렇지 않으면 불가능합니다.

2. 여러 스레드의 동시 호출을 피하기 위해 스레드 안전하지 않은 개체를 저장합니다.

날짜 형식 지정 도구 함수를 작성할 때 가장 먼저 떠오르는 것은 다음과 같습니다.

/** 日期模式 */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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제