现在的位置: 首页 > 综合 > 正文

线程安全和ThreadLocal入门

2013年09月18日 ⁄ 综合 ⁄ 共 2975字 ⁄ 字号 评论关闭

原帖地址:http://javapapers.com/core-java/threadlocal/

尝试翻译,欢迎批评指正。

 

原文地址:http://javapapers.com/core-java/threadlocal/

ThreadLocal的核心概念是没一个线程可以通过get或者set方法访问它自己的、独立初始化的变量的副本。

1. ThreadLocal介绍

为了在多线程环境下不出现任何的冲突,我们希望能否分离一个类的多个实例。对于每一个线程来说,没一个实例都是唯一的。这不过是实现线程安全的一个方式。

线程安全的另外的重要的一点是能够全局访问。可以在线程内部的任何地方进行访问。记住:应该声明成staticfinal的。

2. 什么是线程安全

线程是进程的一条单独的线。当我们提到多线程应用的时候,我们的意思是一个进程的多个线程访问同一行代码。在这个情况下,存在一个线程访问或者修改另一个线程的数据的可能性。当数据不允许这样共享的时候,我们应该做成线程安全的。实现线程安全的方式有下面几种:

· 重入

·互斥(同步机制)

·ThreadLocal

·原子操作

3. 使用ThreadLocal

(引用Joshua Bloch的一段话,巨抽象,我没看懂,......

我们有一个非线程安全的变量,我们想把它变成线程安全的,可以考虑同步机制把对象封闭到同步块中。另外的方式是使用ThreadLocal,为每一个线程持有单独的对象使得变得安全。

4. ThreadLocal的例子

package com.javapapers;

 

import java.text.SimpleDateFormat;

import java.util.Date;

 

public class ThreadLocalExample {

  private static final ThreadLocal formatter = new ThreadLocal() {

 

    protected SimpleDateFormat initialValue() {

      return new SimpleDateFormat("yyyyMMdd HHmm");

    }

  };

 

  public String formatIt(Date date) {

    return formatter.get().format(date);

  }

}

上边的代码中,关键要理解get()方法。他返回的当前线程的ThreadLocal变量的副本。如果当前线程的这个变量还没有值,则通过调用initalValue方法返回第一次初始化的值。

JavaDoc中的例子

下面的例子为每一个线程生成一个唯一的标识符。第一次调用get方法的时候指定一个线程的id,并且在随后的调用中保持不变。

port java.util.concurrent.atomic.AtomicInteger;

 

public class ThreadId {

    // Atomic integer containing the next thread ID to be assigned

    private static final AtomicInteger nextId = new AtomicInteger(0);

 

    // Thread local variable containing each thread's ID

    private static final ThreadLocal threadId =

        new ThreadLocal() {

            @Override protected Integer initialValue() {

                return nextId.getAndIncrement();

        }

    };

 

    // Returns the current thread's unique ID, assigning it if necessary

    public static int get() {

        return threadId.get();

    }

}

5. Java APIThreadLocal 的使用

JDK1.7中,我们有一个叫做ThreadLocalRandom的新类。它用于为并行的线程生成随机数,每一个线程是随机数的种子都是唯一的。这是一个非常酷的功能。

下面的代码是上边的类实现ThreadLocal 的代码:

private static final ThreadLocal localRandom =

    new ThreadLocal() {

        protected ThreadLocalRandom initialValue() {

            return new ThreadLocalRandom();

        }

};

使用ThreadLocalRandom

package com.javapapers;

 

import java.util.concurrent.ThreadLocalRandom;

 

public class ThreadLocalRandomExample {

 

  public static void main(String args[]) throws InterruptedException {

 

    //tossing 3 coins

    for (int i = 0; i < 3; i++) {

      final Thread thread = new Thread() {

 

        public void run() {

          System.out.print(Thread.currentThread().getName() + ":");

 

          // generating 3 random numbers - random for every thread

          for (int j = 0; j < 3; j++) {

            final int random = ThreadLocalRandom.current().nextInt(

                1, 3);

            System.out.print(random + ",");

          }

          System.out.println();

        }

      };

      thread.start();

      thread.join();

    }

  }

}

6. ThreadLocal和内存泄露

ThreadLocal不是一个魔鬼,而是一个优秀的、实用的API。完全取决于我们怎么样去使用。我们应该学会在正确的场合使用合适的工具。我们不能使用大炮打蚊子,但是也不能谴责大炮。

 

PDF文件下载:

http://download.csdn.net/detail/licl19870605/4529958

 

抱歉!评论已关闭.