成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

當(dāng)ThreadLocal碰上線程池

instein / 1141人閱讀

ThreadLocal可以讓線程擁有本地變量,在web環(huán)境中,為了方便代碼解耦,我們通常用它來(lái)保存上下文信息,然后用一個(gè)util類提供訪問(wèn)入口,從controller層到service層可以很方便的獲取上下文。下面我們通過(guò)代碼來(lái)研究一下ThreadLocal。

新建一個(gè)ThreadContext類,用于保存線程上下文信息

public class ThreadContext {
    private static ThreadLocal userResource = new ThreadLocal();

    public static UserObj getUser() {
        return userResource.get();
    }

    public static void bindUser(UserObj user) {
        userResource.set(user);
    }

    public static UserObj unbindUser() {
        UserObj obj = userResource.get();
        userResource.remove();
        return obj;
    }
}

新建一個(gè)sessionFilter ,用來(lái)操作線程變量

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    try {
        // 假設(shè)這里是從cookie拿token信息, 調(diào)用服務(wù)/或者從緩存查詢用戶信息
        // 為了避免后續(xù)邏輯中多次查詢/請(qǐng)求緩存服務(wù)器, 這里拿到user后放到線程本地變量中
        UserObj user = ThreadContext.getUser();
        // 如果當(dāng)前線程中沒(méi)有綁定user對(duì)象,那么綁定一個(gè)新的user
        if (user == null) {
            ThreadContext.bindUser(new UserObj("usertest"));
        }

        filterChain.doFilter(servletRequest, servletResponse);
    } finally {
        // ThreadLocal的生命周期不等于一次request請(qǐng)求的生命周期
        // 每個(gè)request請(qǐng)求的響應(yīng)是tomcat從線程池中分配的線程, 線程會(huì)被下個(gè)請(qǐng)求復(fù)用.
        // 所以請(qǐng)求結(jié)束后必須刪除線程本地變量
        // ThreadContext.unbindUser();
    }
}

新建UserUtils工具類

/**
 * 配合SessionFilter使用,從上下文中取user信息
 */
public class UserUtils {
    public static UserObj getCurrentUser() {
        return ThreadContext.getUser();
    }
}

新建一個(gè)servlet測(cè)試

public class HelloworldServlet extends HttpServlet {

    private static Logger logger = LoggerFactory.getLogger(HelloworldServlet.class);
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        UserObj user = UserUtils.getCurrentUser();
        logger.info(user.getName() + user.hashCode());
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

循環(huán)請(qǐng)求servlet,控制臺(tái)顯示結(jié)果如下??梢园l(fā)現(xiàn)tomcat線程池的初始大小是10個(gè),后面的請(qǐng)求復(fù)用了前面的線程,ThreadContext中的user對(duì)象的hashcode也一樣。

2016-11-29 17:21:35.975  INFO 36672 --- [nio-8080-exec-2] com.zallds.xy.servlet.HelloworldServlet  : usertest818202673
2016-11-29 17:21:38.923  INFO 36672 --- [nio-8080-exec-3] com.zallds.xy.servlet.HelloworldServlet  : usertest1582591702
2016-11-29 17:21:45.810  INFO 36672 --- [nio-8080-exec-4] com.zallds.xy.servlet.HelloworldServlet  : usertest55755037
2016-11-29 17:21:46.773  INFO 36672 --- [nio-8080-exec-5] com.zallds.xy.servlet.HelloworldServlet  : usertest1495466807
2016-11-29 17:21:47.345  INFO 36672 --- [nio-8080-exec-6] com.zallds.xy.servlet.HelloworldServlet  : usertest1149360245
2016-11-29 17:21:47.613  INFO 36672 --- [nio-8080-exec-7] com.zallds.xy.servlet.HelloworldServlet  : usertest518375339
2016-11-29 17:21:47.837  INFO 36672 --- [nio-8080-exec-8] com.zallds.xy.servlet.HelloworldServlet  : usertest92458992
2016-11-29 17:21:48.012  INFO 36672 --- [nio-8080-exec-9] com.zallds.xy.servlet.HelloworldServlet  : usertest944867034
2016-11-29 17:21:48.199  INFO 36672 --- [io-8080-exec-10] com.zallds.xy.servlet.HelloworldServlet  : usertest1410972809
2016-11-29 17:21:48.378  INFO 36672 --- [nio-8080-exec-1] com.zallds.xy.servlet.HelloworldServlet  : usertest805332046
2016-11-29 17:21:48.552  INFO 36672 --- [nio-8080-exec-2] com.zallds.xy.servlet.HelloworldServlet  : usertest818202673
2016-11-29 17:21:48.730  INFO 36672 --- [nio-8080-exec-3] com.zallds.xy.servlet.HelloworldServlet  : usertest1582591702
2016-11-29 17:21:48.903  INFO 36672 --- [nio-8080-exec-4] com.zallds.xy.servlet.HelloworldServlet  : usertest55755037
2016-11-29 17:21:49.072  INFO 36672 --- [nio-8080-exec-5] com.zallds.xy.servlet.HelloworldServlet  : usertest1495466807
2016-11-29 17:21:49.247  INFO 36672 --- [nio-8080-exec-6] com.zallds.xy.servlet.HelloworldServlet  : usertest1149360245
2016-11-29 17:21:49.402  INFO 36672 --- [nio-8080-exec-7] com.zallds.xy.servlet.HelloworldServlet  : usertest518375339

去掉注釋// ThreadContext.unbindUser(); 重新請(qǐng)求,每次從ThreadLocal中拿到的user對(duì)象完全不一樣了。

2016-11-29 17:30:37.150  INFO 36903 --- [nio-8080-exec-1] com.zallds.xy.servlet.HelloworldServlet  : usertest413138571
2016-11-29 17:30:42.932  INFO 36903 --- [nio-8080-exec-2] com.zallds.xy.servlet.HelloworldServlet  : usertest1402191945
2016-11-29 17:30:43.124  INFO 36903 --- [nio-8080-exec-3] com.zallds.xy.servlet.HelloworldServlet  : usertest1957579173
2016-11-29 17:30:43.313  INFO 36903 --- [nio-8080-exec-4] com.zallds.xy.servlet.HelloworldServlet  : usertest1582591702
2016-11-29 17:30:43.501  INFO 36903 --- [nio-8080-exec-5] com.zallds.xy.servlet.HelloworldServlet  : usertest1917479582
2016-11-29 17:30:43.679  INFO 36903 --- [nio-8080-exec-6] com.zallds.xy.servlet.HelloworldServlet  : usertest772036767
2016-11-29 17:30:43.851  INFO 36903 --- [nio-8080-exec-7] com.zallds.xy.servlet.HelloworldServlet  : usertest162020761
2016-11-29 17:30:44.024  INFO 36903 --- [nio-8080-exec-8] com.zallds.xy.servlet.HelloworldServlet  : usertest682232950
2016-11-29 17:30:44.225  INFO 36903 --- [nio-8080-exec-9] com.zallds.xy.servlet.HelloworldServlet  : usertest2140650341
2016-11-29 17:30:44.419  INFO 36903 --- [io-8080-exec-10] com.zallds.xy.servlet.HelloworldServlet  : usertest1327601763
2016-11-29 17:30:44.593  INFO 36903 --- [nio-8080-exec-1] com.zallds.xy.servlet.HelloworldServlet  : usertest647738411
2016-11-29 17:30:44.787  INFO 36903 --- [nio-8080-exec-2] com.zallds.xy.servlet.HelloworldServlet  : usertest944867034
2016-11-29 17:30:45.045  INFO 36903 --- [nio-8080-exec-3] com.zallds.xy.servlet.HelloworldServlet  : usertest1886154520
2016-11-29 17:30:45.317  INFO 36903 --- [nio-8080-exec-4] com.zallds.xy.servlet.HelloworldServlet  : usertest1592904273
2016-11-29 17:30:46.380  INFO 36903 --- [nio-8080-exec-5] com.zallds.xy.servlet.HelloworldServlet  : usertest1410972809
2016-11-29 17:30:46.524  INFO 36903 --- [nio-8080-exec-6] com.zallds.xy.servlet.HelloworldServlet  : usertest1705570689
2016-11-29 17:30:46.692  INFO 36903 --- [nio-8080-exec-7] com.zallds.xy.servlet.HelloworldServlet  : usertest1105134375
2016-11-29 17:30:46.802  INFO 36903 --- [nio-8080-exec-8] com.zallds.xy.servlet.HelloworldServlet  : usertest407377722

ThreadLocal子線程場(chǎng)景

需求新增, 需要在原有的業(yè)務(wù)邏輯中增加一個(gè)給用戶發(fā)送郵件的操作。發(fā)送郵件我們采用異步處理,新建一個(gè)線程來(lái)執(zhí)行。

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    UserObj user = UserUtils.getCurrentUser();
    logger.info(user.getName() + user.hashCode());

    SendEmailTask emailThread = new SendEmailTask();
    new Thread(emailThread).start();

    super.doGet(req, resp);
}

class SendEmailTask implements Runnable {

    @Override
    public void run() {
        UserObj user = UserUtils.getCurrentUser();
        logger.info("子線程中:" + (user == null ? "user為null" : user.getName() + user.hashCode()));
    }
}

主線程中創(chuàng)建異步線程,子線程中能拿到嗎?通過(guò)測(cè)試發(fā)現(xiàn)是不能的

2016-11-29 18:09:16.482  INFO 38092 --- [nio-8080-exec-2] com.zallds.xy.servlet.HelloworldServlet  : usertest1425505918
2016-11-29 18:09:16.483  INFO 38092 --- [       Thread-4] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:user為null
2016-11-29 18:09:20.995  INFO 38092 --- [nio-8080-exec-3] com.zallds.xy.servlet.HelloworldServlet  : usertest1280373552
2016-11-29 18:09:20.996  INFO 38092 --- [       Thread-5] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:user為null

子線程怎么拿到父線程的ThreadLocal數(shù)據(jù)?jdk給我們提供了解決辦法,ThreadLocal有一個(gè)子類InheritableThreadLocal,創(chuàng)建ThreadLocal時(shí)候我們采用InheritableThreadLocal類可以實(shí)現(xiàn)子線程獲取到父線程的本地變量。

private static ThreadLocal userResource = new InheritableThreadLocal();

然后子線程中就可以正常拿到user對(duì)象了

2016-11-29 19:07:01.518  INFO 39644 --- [nio-8080-exec-2] com.zallds.xy.servlet.HelloworldServlet  : usertest495550128
2016-11-29 19:07:01.518  INFO 39644 --- [       Thread-4] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest495550128
2016-11-29 19:07:05.839  INFO 39644 --- [nio-8080-exec-3] com.zallds.xy.servlet.HelloworldServlet  : usertest1851717404
2016-11-29 19:07:05.840  INFO 39644 --- [       Thread-5] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest1851717404

ThreadLocal 子線程傳遞-線程池場(chǎng)景

當(dāng)我們執(zhí)行異步任務(wù)時(shí),大多會(huì)采用線程池的機(jī)制(如Executor)。這樣就會(huì)存在一個(gè)問(wèn)題,即使父線程已經(jīng)結(jié)束,子線程依然存在并被池化。這樣,線程池中的線程在下一次請(qǐng)求被執(zhí)行的時(shí)候,ThreadLocal的get()方法返回的將不是當(dāng)前線程中設(shè)定的變量,因?yàn)槌刂械摹白泳€程”根本不是當(dāng)前線程創(chuàng)建的,當(dāng)前線程設(shè)定的ThreadLocal變量也就無(wú)法傳遞給線程池中的線程。
我們修改一下發(fā)送郵件的代碼,改用線程池來(lái)實(shí)現(xiàn)。

2016-11-29 19:51:51.973  INFO 40937 --- [nio-8080-exec-1] com.zallds.xy.servlet.HelloworldServlet  : usertest1417641261
2016-11-29 19:51:51.974  INFO 40937 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest1417641261
2016-11-29 19:51:55.746  INFO 40937 --- [nio-8080-exec-2] com.zallds.xy.servlet.HelloworldServlet  : usertest1116537955
2016-11-29 19:51:55.746  INFO 40937 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest1417641261
2016-11-29 19:51:58.825  INFO 40937 --- [nio-8080-exec-3] com.zallds.xy.servlet.HelloworldServlet  : usertest1489938856
2016-11-29 19:51:58.826  INFO 40937 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest1417641261

可以發(fā)現(xiàn)發(fā)送郵件的任務(wù)三次用的都是同一個(gè)線程[pool-1-thread-1],第一次子線程和父線程中的user對(duì)象相同,后面的“子線程”(前面提到過(guò),后面的已經(jīng)不是子線程了)中的user對(duì)象都是和第一個(gè)父線程中的相同。
那么在線程池的場(chǎng)景下,怎么能讓“子線程”正常拿到父線程傳遞過(guò)來(lái)的變量呢?如果我們能在創(chuàng)建task的時(shí)候主動(dòng)傳遞過(guò)去就好了。按照這個(gè)想法我們來(lái)實(shí)施一下。
繼續(xù)修改代碼

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    UserObj user = UserUtils.getCurrentUser();
    logger.info(user.getName() + user.hashCode());

    SendEmailTask emailThread = new SendEmailTask();

    executor.execute(new UserRunnable(emailThread, user));
    super.doGet(req, resp);
}

/**
 * 做一個(gè)wrapper, 將目標(biāo)任務(wù)做一層包裝, 在run方法中傳遞線程本地變量
 */
class UserRunnable implements Runnable {
    /**
     * 目標(biāo)任務(wù)對(duì)象
     */
    Runnable runnable;
    /**
     * 要綁定的user對(duì)象
     */
    UserObj user;

    public UserRunnable(Runnable runnable, UserObj user) {
        this.runnable = runnable;
        this.user = user;
    }

    @Override
    public void run() {
        ThreadContext.bindUser(user);
        runnable.run();
        ThreadContext.unbindUser();
    }
}

class SendEmailTask implements Runnable {

    @Override
    public void run() {
        UserObj user = UserUtils.getCurrentUser();
        logger.info("子線程中:" + (user == null ? "user為null" : user.getName() + user.hashCode()));
    }
}

重新請(qǐng)求,得到我們想要的結(jié)果

2016-11-29 20:04:12.153  INFO 41258 --- [nio-8080-exec-1] com.zallds.xy.servlet.HelloworldServlet  : usertest1565180744
2016-11-29 20:04:12.154  INFO 41258 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest1565180744
2016-11-29 20:04:14.142  INFO 41258 --- [nio-8080-exec-2] com.zallds.xy.servlet.HelloworldServlet  : usertest481396704
2016-11-29 20:04:14.142  INFO 41258 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest481396704
2016-11-29 20:04:15.248  INFO 41258 --- [nio-8080-exec-3] com.zallds.xy.servlet.HelloworldServlet  : usertest400717395
2016-11-29 20:04:15.249  INFO 41258 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest400717395

到此為止,ThreadLocal常見(jiàn)的場(chǎng)景和對(duì)應(yīng)解決方案應(yīng)該可以滿足了。接下來(lái)就是怎么在實(shí)際應(yīng)用中運(yùn)用了。

為了引出此文的初衷以及后面要講的東西,針對(duì)最后一個(gè)解決方案,我們可以進(jìn)一步完善一下。

ThreadContext.bindUser(user);
runnable.run();
ThreadContext.unbindUser();

這個(gè)地方在bind的時(shí)候是直接覆蓋,無(wú)法對(duì)線程之前的狀態(tài)進(jìn)行保存和恢復(fù)。要實(shí)現(xiàn)這一點(diǎn),我們可以抽象一個(gè)ThreadState來(lái)保存線程的狀態(tài),在bind之前保存original,任務(wù)執(zhí)行完以后進(jìn)行restore。

public interface ThreadState {
    void bind();

    void restore();

    void clear();
}

public class UserThreadState implements ThreadState {
    private UserObj original;

    private UserObj user;

    public UserThreadState(UserObj user) {
        this.user = user;
    }

    @Override
    public void bind() {
        this.original = ThreadContext.getUser();

        ThreadContext.bindUser(this.user);
    }

    @Override
    public void restore() {
        ThreadContext.bindUser(this.original);
    }

    @Override
    public void clear() {
        ThreadContext.unbindUser();
    }
}


protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    UserObj user = UserUtils.getCurrentUser();
    logger.info(user.getName() + user.hashCode());

    SendEmailTask emailThread = new SendEmailTask();

    executor.execute(new UserRunnable(emailThread, new UserThreadState(user)));
    super.doGet(req, resp);
}

/**
 * 做一個(gè)wrapper, 將目標(biāo)任務(wù)做一層包裝, 在run方法中傳遞線程本地變量
 */
class UserRunnable implements Runnable {
    /**
     * 目標(biāo)任務(wù)對(duì)象
     */
    Runnable runnable;
    /**
     * 要綁定的user對(duì)象
     */
    UserThreadState userThreadState;

    public UserRunnable(Runnable runnable, UserThreadState userThreadState) {
        this.runnable = runnable;
        this.userThreadState = userThreadState;
    }

    @Override
    public void run() {
        userThreadState.bind();
        runnable.run();
        userThreadState.restore();
        UserObj userOrig = UserUtils.getCurrentUser();
        logger.info("original:" + userOrig.getName() + userOrig.hashCode());
    }
}

class SendEmailTask implements Runnable {

    @Override
    public void run() {
        UserObj user = UserUtils.getCurrentUser();
        logger.info("子線程中:" + (user == null ? "user為null" : user.getName() + user.hashCode()));
    }
}

實(shí)現(xiàn)效果是相同的,至于為什么三次的original對(duì)象都是一樣的,通過(guò)前面的說(shuō)明應(yīng)該能夠理解

2016-11-29 20:19:48.694  INFO 41671 --- [nio-8080-exec-1] com.zallds.xy.servlet.HelloworldServlet  : usertest114760676
2016-11-29 20:19:48.699  INFO 41671 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest114760676
2016-11-29 20:19:48.700  INFO 41671 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : original:usertest114760676
2016-11-29 20:19:57.123  INFO 41671 --- [nio-8080-exec-2] com.zallds.xy.servlet.HelloworldServlet  : usertest941302199
2016-11-29 20:19:57.123  INFO 41671 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest941302199
2016-11-29 20:19:57.123  INFO 41671 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : original:usertest114760676
2016-11-29 20:20:04.385  INFO 41671 --- [nio-8080-exec-3] com.zallds.xy.servlet.HelloworldServlet  : usertest1489938856
2016-11-29 20:20:04.385  INFO 41671 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : 子線程中:usertest1489938856
2016-11-29 20:20:04.385  INFO 41671 --- [pool-1-thread-1] com.zallds.xy.servlet.HelloworldServlet  : original:usertest114760676

由于在使用shiro框架的SecurityUtils.getSubject()過(guò)程中碰到問(wèn)題,才有了本文的示例,例子中的部分代碼參考了shiro框架的實(shí)現(xiàn)機(jī)制。后面會(huì)再研究一下shiro的subject相關(guān)設(shè)計(jì)。

http://shiro.apache.org/subject.html

作者:?99793933e682
原文地址:?https://www.jianshu.com/p/85d96fe9358b

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/75757.html

相關(guān)文章

  • Java 并發(fā)設(shè)計(jì)模式

    摘要:并發(fā)設(shè)計(jì)模式一模式的使用表示線程本地存儲(chǔ)模式。為不同的任務(wù)創(chuàng)建不同的線程池,這樣能夠有效的避免死鎖問(wèn)題。兩階段終止,即將線程的結(jié)束分為了兩個(gè)階段,第一個(gè)階段是一個(gè)線程向另一個(gè)線程發(fā)送終止指令,第二個(gè)階段是線程響應(yīng)終止指令。 Java 并發(fā)設(shè)計(jì)模式 一、Thread Local Storage 模式 1. ThreadLocal 的使用 Thread Local Storage 表示線程...

    zero 評(píng)論0 收藏0
  • ThreadLocal就是這么簡(jiǎn)單

    摘要:簡(jiǎn)要言之往中填充的變量屬于當(dāng)前線程,該變量對(duì)其他線程而言是隔離的。在辦理時(shí)又告訴機(jī)構(gòu)來(lái),把我的身份證房產(chǎn)證學(xué)生證通通給他。 前言 今天要研究的是ThreadLocal,這個(gè)我在一年前學(xué)習(xí)JavaWeb基礎(chǔ)的時(shí)候接觸過(guò)一次,當(dāng)時(shí)在baidu搜出來(lái)的第一篇博文ThreadLocal,在評(píng)論下很多開(kāi)發(fā)者認(rèn)為那博主理解錯(cuò)誤,給出了很多有關(guān)的鏈接來(lái)指正(可原博主可能沒(méi)上博客了,一直沒(méi)做修改)。我...

    zhouzhou 評(píng)論0 收藏0
  • 想進(jìn)大廠?50個(gè)多線程面試題,你會(huì)多少?(一)

    摘要:下面是線程相關(guān)的熱門(mén)面試題,你可以用它來(lái)好好準(zhǔn)備面試。線程安全問(wèn)題都是由全局變量及靜態(tài)變量引起的。持有自旋鎖的線程在之前應(yīng)該釋放自旋鎖以便其它線程可以獲得自旋鎖。 最近看到網(wǎng)上流傳著,各種面試經(jīng)驗(yàn)及面試題,往往都是一大堆技術(shù)題目貼上去,而沒(méi)有答案。 不管你是新程序員還是老手,你一定在面試中遇到過(guò)有關(guān)線程的問(wèn)題。Java語(yǔ)言一個(gè)重要的特點(diǎn)就是內(nèi)置了對(duì)并發(fā)的支持,讓Java大受企業(yè)和程序員...

    wow_worktile 評(píng)論0 收藏0
  • Java 并發(fā)方案全面學(xué)習(xí)總結(jié)

    摘要:進(jìn)程線程與協(xié)程它們都是并行機(jī)制的解決方案。選擇是任意性的,并在對(duì)實(shí)現(xiàn)做出決定時(shí)發(fā)生。線程池的大小一旦達(dá)到最大值就會(huì)保持不變,如果某個(gè)線程因?yàn)閳?zhí)行異常而結(jié)束,那么線程池會(huì)補(bǔ)充一個(gè)新線程。此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。 并發(fā)與并行的概念 并發(fā)(Concurrency): 問(wèn)題域中的概念—— 程序需要被設(shè)計(jì)成能夠處理多個(gè)同時(shí)(或者幾乎同時(shí))發(fā)生的事件 并行(Parallel...

    mengera88 評(píng)論0 收藏0
  • ThreadLocal 線程安全機(jī)制與小地雷

    摘要:多線程類庫(kù)對(duì)于共享數(shù)據(jù)的讀寫(xiě)控制主要采用鎖機(jī)制保證線程安全,本文所要探究的則采用了一種完全不同的策略。所以出現(xiàn)內(nèi)存泄露的前提必須是持有的線程一直存活,這在使用線程池時(shí)是很正常的,在這種情況下一直不會(huì)被,因?yàn)? Java 多線程類庫(kù)對(duì)于共享數(shù)據(jù)的讀寫(xiě)控制主要采用鎖機(jī)制保證線程安全,本文所要探究的 ThreadLocal 則采用了一種完全不同的策略。ThreadLocal 不是用來(lái)解決共享數(shù)...

    xiao7cn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

instein

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<