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个时,可能有些线程需要等待。
java并发编程基础——线程相关的类的更多相关文章
- Java并发编程基础-线程安全问题及JMM(volatile)
什么情况下应该使用多线程 : 线程出现的目的是什么?解决进程中多任务的实时性问题?其实简单来说,也就是解决“阻塞”的问题,阻塞的意思就是程序运行到某个函数或过程后等待某些事件发生而暂时停止 CPU 占 ...
- java并发编程基础——线程的创建
一.基础概念 1.进程和线程 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据 ...
- java并发编程基础——线程池
线程池 由于启动一个线程要与操作系统交互,所以系统启动一个新的线程的成本是比较高的.在这种情况下,使用线程池可以很好的提升性能,特别是程序中涉及创建大量生命周期很短暂的线程时. 与数据库连接池类似,线 ...
- java并发编程基础——线程同步
线程同步 一.线程安全问题 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安 ...
- java并发编程基础——线程通信
线程通信 当线程在系统内运行时,程序通常无法准确的控制线程的轮换执行,但我们可以通过一些机制来保障线程的协调运行 一.传统的线程通信 传统的线程通信主要是通过Object类提供的wait(),noti ...
- Java并发编程基础
Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程池的使用(转)
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程池的使用(转载)
转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
随机推荐
- TensorRT-安装-使用
TensorRT-安装-使用 一.安装 这里 是英伟达提供的安装指导,如果有仔细认真看官方指导,基本上按照官方的指导肯定能安装成功. 问题是肯定有很多人不愿意认真看英文指导,比如说我就是,我看那个指导 ...
- https://www.jianshu.com/writer#/notebooks/164311/notes/88906048/preview
什么是 webassembly 在 2019 年 12 月之前,如果你要编写一个web页面,那一定离不开 html.css.js 这三个好兄弟.在 2019 年 12 月之后 W3C 宣布 webas ...
- day05对象和类
day06作业: 第一题:分析以下需求,并用代码实现 手机类Phone 属性: 品牌brand 价格price 行为: 打电话call() 发短信sendMessage() 玩游戏playGame() ...
- 狂神说redis笔记(三)
八.Redis.conf 容量单位不区分大小写,G和GB有区别 可以使用 include 组合多个配置问题 网络配置 日志 # 日志 # Specify the server verbosity le ...
- 四、提高SSH服务安全
配置基本安全策略 [root@proxy ~]# vim /etc/ssh/sshd_config //调整sshd服务配置 .. .. Protocol 2 ...
- UF_LAYER 图层操作
Open C uc5007uc5008uc5009UF_LAYER_ask_category_infoUF_LAYER_ask_category_tagUF_LAYER_ask_statusUF_LA ...
- SVN报错“Failed to run the WC DB work queue associated with”解决办法
最近在更新SVN上的ISO代码时,失败报错: Failed to run the WC DB work queue associated with "目录/文件",clean u ...
- [apue] linux 文件访问权限那些事儿
前言 说到 linux 上的文件权限,其实我们在说两个实体,一是文件,二是进程.一个进程能不能访问一个文件,其实由三部分内容决定: 文件的所有者.所在的组: 文件对所有者.组用户.其它用户设置的权限访 ...
- Perm 排列计数
题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很 ...
- Go语言中的有缓冲channel和无缓冲channel区别
Go语言中的有缓冲channel和无缓冲channel区别 结论 ch1:=make(chan int)// 无缓冲 ch2:=make(chan int,1)// 有缓冲 无缓冲: 当向ch1中存值 ...