zoukankan      html  css  js  c++  java
  • 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个时,可能有些线程需要等待。

  • 相关阅读:
    python 类函数
    scala 排序
    php基础-面向对象
    PHP基础-常用的数组相关处理函数
    PHP基础-PHP中预定义的超全局数组
    PHP基础-数组
    装饰器
    Python3.x 文件操作练习
    Python3.x 文件操作
    Python3 内置函数
  • 原文地址:https://www.cnblogs.com/jnba/p/10636701.html
Copyright © 2011-2022 走看看