java并发编程基础——线程相关的类

线程相关类

java还为线程安全提供了一些工具类。

一、ThreadLocal类(Thread Local Variable)

ThreadLocal类,是线程局部变量的意思。功用非常简单,就是为每一个使用该变量的线程提供一个变量值的副本,使没一个线程都可以独立的改变自己的副本,而不会和其他副本冲突。

ThreadLocal提供了3个public方法

T get();返回此线程局部变量中当前线程副本中的值

void remove():删除此线程局部变量中当前线程的值

void set(T value):设置此线程局部变量中当前线程副本中的值

ThreadLocal也是为了解决多线程中对同一变量访问的冲突。普通的同步机制中是通过对象加锁来实现对同一变量的安全访问。

ThreadLocal从另一角度来解决多线程的并发,它是将需要并发访问的资源复制成多份,每个线程拥有一份资源,没必要对该变量进行同步了。

ThreadLocal并不能代替同步机制,两者的问题领域不同,同步机制是为了同步多个线程对相同的资源进行并发访问,是多线程之间进行通信的有效方式。ThreadLocal是为了隔离多个线程的数据共享,从根本上避免多个线程之间对共享资源的竞争。

最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。

下面小程序说明了ThreadLocal能达到在每个线程中创建变量副本的效果:

package threadtest;
public class ThreadTest implements Runnable{
 
    private ThreadLocal<Integer> i =new ThreadLocal<>();
    public int getI() {
        return i.get();
    }
 
    public void setI(int i) {
        this.i.set(i);
    }
 
    @Override
    public void run() {
        for(i.set(0);i.get()<100;i.set(i.get()+1)) {
            System.out.println(Thread.currentThread().getName() + "--------->" + i.get());
        }
         
    }
    public static void main(String[] args)  {
        //两个线程,各自打印各自的值
        ThreadTest tt = new ThreadTest();
        Thread t1 = new Thread(tt,"t1");
        Thread t2 = new Thread(tt,"t2");
        t1.start();
        t2.start();    
    }
}

结果:i变量两个线程各自不影响

t1--------->0
t2--------->0
t1--------->1
t2--------->1
t1--------->2
t2--------->2
t1--------->3
t2--------->3
...
t2--------->94
t2--------->95
t2--------->96
t2--------->97
t2--------->98
t2--------->99
t1--------->15
t1--------->16
t1--------->17
t1--------->18
...
t1--------->97
t1--------->98
t1--------->99

二、包装线程不安全的集合

Java集合中ArrayList,LinkedList,HashSet,TreeSet,HashMap,TreeMap等都是线程不安全的,就是多个线程并发向这些集合中存取数据,可能会破坏数据的完整性。

如果要多线程访问这些集合,就需要包装下,需要用到Collections提供的静态方法把这些集合包装成安全的集合,方法如下:

static <T> Collection<T> synchronizedCollection(Collection<T> c)

static <T> List<T> synchronizedList(List<T> list)

static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)

static <T> Set<T> synchronizedSet(Set<T> s)

static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)

static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)

//将ArrayList包装成安全的
List<String> l =Collections.synchronizedList(new ArrayList<String>());

三、线程安全的集合类

Java5开始,java.util.concurrent包下提供了大量支持高并发访问的集合接口和实现类

主要分为两类:

以Concurrent开头的集合类,如:ConcurrentHashMap,ConcurrentSkipListMap,ConcurrentSkipListSet,ConcurrentLinkedQueue,ConcurrentLinkedDeque

以CopyOnWrite开头的集合类,如: CopyOnWriteArrayList,CopyOnWriteArraySet.

其中Concurrent开头的集合类代表了并发访问的集合,支持多线程并发写入访问,这些写入程序的所有操作都是线程安全的,但读取不会锁定。

当多个线程共享访问一个公共集合时,ConcurrentLinkedQueue是一个不错的选择。ConcurrentLinkedQueue实现了多线程的高效访问,个线程访问时无需等待

在默认情况下ConcurrentHashMap支持16个线程并发写入,超过16个时,可能有些线程需要等待。

原文地址:https://www.cnblogs.com/jnba/p/10636701.html