线程相关类

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个时,可能有些线程需要等待。

java并发编程基础——线程相关的类的更多相关文章

  1. Java并发编程基础-线程安全问题及JMM(volatile)

    什么情况下应该使用多线程 : 线程出现的目的是什么?解决进程中多任务的实时性问题?其实简单来说,也就是解决“阻塞”的问题,阻塞的意思就是程序运行到某个函数或过程后等待某些事件发生而暂时停止 CPU 占 ...

  2. java并发编程基础——线程的创建

    一.基础概念 1.进程和线程 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据 ...

  3. java并发编程基础——线程池

    线程池 由于启动一个线程要与操作系统交互,所以系统启动一个新的线程的成本是比较高的.在这种情况下,使用线程池可以很好的提升性能,特别是程序中涉及创建大量生命周期很短暂的线程时. 与数据库连接池类似,线 ...

  4. java并发编程基础——线程同步

    线程同步 一.线程安全问题 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安 ...

  5. java并发编程基础——线程通信

    线程通信 当线程在系统内运行时,程序通常无法准确的控制线程的轮换执行,但我们可以通过一些机制来保障线程的协调运行 一.传统的线程通信 传统的线程通信主要是通过Object类提供的wait(),noti ...

  6. Java并发编程基础

    Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...

  7. Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  8. Java并发编程:线程池的使用(转)

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  9. Java并发编程:线程池的使用(转载)

    转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

随机推荐

  1. 自主数据类型:在TVM中启用自定义数据类型探索

    自主数据类型:在TVM中启用自定义数据类型探索 介绍 在设计加速器时,一个重要的决定是如何在硬件中近似地表示实数.这个问题有一个长期的行业标准解决方案:IEEE 754浮点标准.1.然而,当试图通过构 ...

  2. 新的微芯片MCU增加了来自外部闪存的安全引导保护

    新的微芯片MCU增加了来自外部闪存的安全引导保护 New Microchip MCU Adds Secure Boot Protection from External Flash 对于从外部SPI闪 ...

  3. 整理AI性能指标

    整理AI性能指标 Sorting out AI performance metrics 推理性能的最佳衡量标准是什么? 在人工智能加速器的世界里,对于给定的算法,芯片的性能经常以每秒万亿次的运算量(T ...

  4. python_selenium 之logging模块入门及调用实战

    一.logging模块是什么? 是Python内置的标准模块,主要用于输出运行日志 二.日志的作用 日志是代码的必要组成部分 记录日志能显示程序当前运行状态 出问题后定位当时问题 三.python日志 ...

  5. Qt中的布局浅析与弹簧的使用,以及Qt居中的两种方法

    1. 布局 为什么要布局: 布局之后窗口的排列是有序的 布局之后窗口的大小发生变化, 控件的大小也会对应变化 如果不对控件布局, 窗口显示出来之后有些控件的看不到的 布局是可以嵌套使用 常用的布局方式 ...

  6. UiPath中恢复依赖项失败的解决方法

    目录 序言 正文 什么是依赖包? 如何查看项目使用了哪些版本的依赖包? 一.项目内查看 二.查看项目的 JSON 文件 问题根源 解决方法 一.「等」字诀 二.切换网络环境(根治) 三.手动复制依赖包 ...

  7. P1828 [USACO3.2]香甜的黄油 Sweet Butter

    题目描述 农夫$John$发现做出全威斯康辛州最甜的黄油的方法:糖.把糖放在一片牧场上,他知道$N(1\leqslant N\leqslant 500)$只奶牛会过来舔它,这样就能做出能卖好价钱的超甜 ...

  8. 从零开始学架构(三)UML建模

    文章大纲 1.  文章介绍 2.  UML概述 3.  静态模型 4.  动态模型 5.  UML建模的一般过程 一.文章介绍 1.1为什么学习UML (1)UML是一种软件架构的模型表现方法,用于项 ...

  9. centos7安装JDK、CentOS

    1.安装JDK 1.1查看系统是否已有自带的JDK rpm -qa |grep java rpm -qa |grep jdk rpm -qa |grep gcj 1.2卸载已有安装 如果没有输出信息, ...

  10. python3 依赖倒置原则示例

    场景 针对园区停车信息,需要对各个公司提供的停车数据进行整合并录入自家公司的大数据平台 数据的录入无外乎就是对数据的增删改查 下面上一个常规的写法(未符合依赖倒置),整合来自 长安和丰田 的停车数据 ...