摘要:盡量少使用全局變量變量不是常量線程封閉比較好的封閉方法維護的是一個這個是線程的名稱多為我們所有封閉的值作為。在線程執行完之后將中的數據清空防止內存溢出。最后我們用測試發現打印了線程,中變量值只要是一個線程中不管在哪個類中都是共享的。
我們可以通過把對象設計成不可變對象來躲避并發,我們還可以通過使用線程封閉來實現線程安全,所謂線程封閉
就是將數據都封裝到一個線程里,不讓其他線程訪問。
Ad-hoc 線程封閉程序控制實現,比較脆弱,盡量少用
堆棧封閉:局部變量,無并發問題,在項目中使用最多,簡單說就是局部變量,方法的變量都拷貝到線程的堆棧中,只有這個線程能訪問到。盡量少使用全局變量(變量不是常量)
ThreadLocal線程封閉:比較好的封閉方法
ThreadLocal維護的是一個map 這個map是線程的名稱多為key 我們所有封閉的值作為value。
我們做使用Filter做登錄操作都做過,我們現在來使用ThreadLoad來存儲一下用戶信息。
public class RequestHolder { private final static ThreadLocalrequestHolder = new ThreadLocal<>(); public static void add(Long id) { requestHolder.set(id); } public static Long getId() { return requestHolder.get(); } public static void remove() { requestHolder.remove(); } }
聲明一個ThreadLoad對象用來存儲ThreadLoad信息。
@Slf4j public class HttpFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; log.info("do filter, {}, {}", Thread.currentThread().getId(), request.getServletPath()); RequestHolder.add(Thread.currentThread().getId()); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { }
@Slf4j public class HttpInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("preHandle"); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { RequestHolder.remove(); log.info("afterCompletion"); return; } }
定義filter的內容,我們在filter中將線程id加入到ThreadLoad中,然后在controller中獲取,看看能不能獲取的到。在線程執行完之后將ThreadLoad中的數據清空防止內存溢出。
@Controller @RequestMapping("/threadLocal") public class ThreadLocalController { @RequestMapping("/test") @ResponseBody public Long test() { return RequestHolder.getId(); } }
最后我們用postman測試發現打印了線程id,ThreadLoad中變量值只要是一個線程中不管在哪個類中都是共享的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/74486.html
摘要:當某個不應該發布的對象被發布時,這種情況被稱為逸出。線程安全共享線程安全的對象在其內部實現同步,因此多線程可以通過對象的公有接口來進行訪問而不需要進一步的同步。 前言 本系列博客是對《Java并發編程實戰》的一點總結,本篇主要講解以下幾個內容,內容會比較枯燥。可能大家看標題不能能直觀的感受出到底什么意思,這就是專業術語,哈哈,解釋下,術語(terminology)是在特定學科領域用...
摘要:線程封閉當訪問共享的可變數據時,通常需要使用同步。如果僅在單線程內訪問數據,就不要同步。這種技術成為線程封閉。棧封閉棧封閉是線程封閉的一種特例,在棧封閉中,只能通過局部變量才能訪問對象。,對象是正確創建的。 線程封閉 當訪問共享的可變數據時,通常需要使用同步。一種避免使用同步的方式就是不共享數據。如果僅在單線程內訪問數據,就不要同步。這種技術成為線程封閉(Thread Confine...
摘要:線程啟動規則對象的方法先行發生于此線程的每一個動作。所以局部變量是不被多個線程所共享的,也就不會出現并發問題。通過獲取到數據,放入當前線程處理完之后將當前線程中的信息移除。主線程必須在啟動其他線程后立即調用方法。 一、線程安全性 定義:當多個線程訪問某個類時,不管運行時環境采用何種調度方式,或者這些線程將如何交替執行,并且在主調代碼中不需要任何額外的同步或協同,這個類都能表現出正確的行...
摘要:什么時候會出現線程不安全操作并非原子。只有單個組件,且它是線程安全的。這種情況下,就是的線程安全實際是委托給了整個表現出了線程安全。 當多個線程去訪問某個類時,如果類會表現出我們預期出現的行為,那么可以稱這個類是線程安全的。 什么時候會出現線程不安全? 操作并非原子。多個線程執行某段代碼,如果這段代碼產生的結果受不同線程之間的執行時序影響,而產生非預期的結果,即發生了競態條件,就會...
摘要:是需要我們去處理很多事情,為了防止多線程給我們帶來的安全和性能的問題下面就來簡單總結一下我們需要哪些知識點來解決多線程遇到的問題。 前言 不小心就鴿了幾天沒有更新了,這個星期回家咯。在學校的日子要努力一點才行! 只有光頭才能變強 回顧前面: 多線程三分鐘就可以入個門了! Thread源碼剖析 本文章的知識主要參考《Java并發編程實戰》這本書的前4章,這本書的前4章都是講解并發的基...
閱讀 2186·2020-06-12 14:26
閱讀 2490·2019-08-29 16:41
閱讀 1890·2019-08-29 15:28
閱讀 2458·2019-08-26 13:43
閱讀 757·2019-08-26 13:37
閱讀 2779·2019-08-23 18:13
閱讀 2801·2019-08-23 15:31
閱讀 1020·2019-08-23 14:10