线程相关类

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. 使用multus实现管理网和业务网分离——calico和flannel共存

    多个网络层面的需求 一开始为k8s集群搭建了calico网络,所有的容器都用calico对应的网卡进行通信.为了实现网络监控的清爽,想把管理组件,例如日志.统计.监控等组件挪到另外一个网络.于是产生一 ...

  2. 骑士CMS<6.0.48 模板注入文件包含漏洞复现及遇到的坑

    1.坑 payload:variable=1&tpl=<?php phpinfo(); ob_flush();?>/r/n<qscms/company_show 列表名=&q ...

  3. 十、使用Varnish加速Web

    使用Varnish加速Web 构建Web服务器(web1) [root@web1 ~]# yum  -y  install  httpd [root@web1 ~]# systemctl start ...

  4. .NET Core/.NET5/.NET6 开源项目汇总5:权限管理系统项目

    系列目录     [已更新最新开发文章,点击查看详细] 企业管理系统一般包含后台管理UI.组织机构管理.权限管理.日志.数据访问.表单.工作流等常用必备功能.下面收集的几款优秀开源的管理系统,值得大家 ...

  5. 一个线上 Maven 诡异问题排查过程

    å. 前言 现在的大部分 Java 应用基本都是通过 Maven 进行组织的,不论是分布式应用还是单体集群应用往往都会通过一个 父 POM 加若干子 POM 完成项目的组织.然而这种多应用多模块的拆分 ...

  6. ceph-csi源码分析(2)-组件启动参数分析

    更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi源码分析(2)-组件启动参数分析 ceph-csi组件的源码分析分为五部分: ...

  7. kubernetes关闭基于角色的访问控制-匿名访问

    1.关闭基于角色的访问控制 如果正在使用一个带有RBAC机制的Kubernetes集群,服务账户可能不会被授权访问API服务器(或只有部分授权).目前最简单的方式就是运行下面的命令查询API服务器,从 ...

  8. 18、linux文件属性

    文件的描述信息: [root@centos6 /]# ls -lih 总用量 118K 3538945 drwxr-xr-x 3 root root 4.0K 8月 23 17:12 app 3276 ...

  9. 12、elk的使用(1)

    12.0.架构图: 服务器名称 ip地址 controller-node1(主) 172.16.1.90 slave-node1(从) 172.16.1.91 12.1.elk介绍: (1)ELK是三 ...

  10. Prometheus(一):Web服务环境监控

    写在前面 现每个后端的同学的日常都在跟服务(接口)打交道,维护老的比较大单体应用.按业务拆得相对比较细的新服务.无论企业内部用的,面向用户的前端的服务.流量大的有流量小的,有重要的有不那么重要的. 但 ...