hash是线程安全的吗?怎么解决?_这次进程、线程、多线程和线程安全问题,一次性帮你全解决了...

1. 什么是进程
- 一个软件,在操作系统中运行时,我们称其为进程。
- 进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元。
2. 什么是线程
- 在一个进程中,每个独立的功能都需要独立的去运行,这时又需要把当前这个进程划分成多个运行区域,每个独立的小区域(小单元)称为一个线程。线程是进程的一个实体,是 CPU 调度和分派的基本单位,是比进程更小的能独立运行的基本单位。
- 一个程序至少有一个进程,一个进程至少有一个线程。
3. 什么是多线程
- 首先我们来了解一下串行、并行和并发三个概念,这有助于我们了解多线程。串行:一条线程按照顺序依次执行所有任务。并行:同一时间多个线程同时执行,没有执行的先后顺序。并发:同一时间有多个可以执行的线程,一条执行,其它等待。
- 一个进程如果只执行一条执行任务或一个线程依次执行多个执行任务,则称为单线程程序。一个进程拥有多个执行任务,并且同时开启多个线程去完成这些任务(并发),则称为多线程程序。
- 多个线程同步执行多个任务,这样做的优点是防止线程堵塞,增强用户体验和程序的效率,但同时也会面临一个问题:多个线程同时访问相同的资源并进行读写操作可能会出现线程安全问题。
4. 如何实现多线程
- 在Java中实现多线程一共有四种方法,这四种方法其实也可以分为两类
- java 5 之前就有的方法1.继承Thread类,重写run方法,没有返回值(其实Thread类本身也实现了Runnable接口)2.实现Runnable接口,重写run方法,没有返回值
- java 5 之后出现的方法3.实现Callable接口,重写call方法,有返回值4.使用线程池
- 1.继承Thread
public class MyThread extends Thread {@Overridepublic void run() {System.out.println("my thread .....");}
}
- 2.实现Runable接口
public class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("my runnable ....");}
}
- 3.实现 Callable 接口
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;class MyTask implements Callable<Integer> {private int upperBounds;public MyTask(int upperBounds) {this.upperBounds = upperBounds;}@Overridepublic Integer call() throws Exception {int sum = 0;for(int i = 1; i <= upperBounds; i++) {sum += i;}return sum;}
}
class Test01 {public static void main(String[] args) throws Exception {List<Future<Integer>> list = new ArrayList<>();ExecutorService service = Executors.newFixedThreadPool(10);for(int i = 0; i < 10; i++) {list.add(service.submit(new MyTask((int) (Math.random() *100))));}int sum = 0;for(Future<Integer> future : list) {// while(!future.isDone()) ;sum += future.get();}System.out.println(sum);}
}
- 4.实现线程池,Java API 提供了 Executor 框架让你可以创建不同的线程池,有单线程的,也有多线程的相关的。共有4种线程池:
- 1)newCachedThreadPool 创建一个可缓存线程池
public void cacheThreadPoolTest() {ExecutorService cachedThreadPool = Executors.newCachedThreadPool();for (int i = 1; i <= 5; i++) {final int j = i;try {Thread.sleep(j * 1);} catch (InterruptedException e) {e.printStackTrace();}cachedThreadPool.execute(()->out.println("线程:" + Thread.currentThread().getName() + ",执行:" + j));}}
- 2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数。
public void fixTheadPoolTest() {ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);for (int i = 0; i < 5; i++) {final int j = i;fixedThreadPool.execute(() -> {out.println("线程:" + Thread.currentThread().getName() + ",执行:" + j);try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}});}
}
- 3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
public void sceduleThreadPoolTest() {ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);Runnable r1 = () -> out.println("线程:" + Thread.currentThread().getName() + ",执行:3秒后执行此任务");scheduledThreadPool.schedule(r1, 3, TimeUnit.SECONDS);Runnable r2 = () -> out.println("线程:" + Thread.currentThread().getName() + ",执行:延迟2秒执行一次后每1秒执行一次");scheduledThreadPool.scheduleAtFixedRate(r2, 2, 1, TimeUnit.SECONDS);Runnable r3 = () -> out.println("线程:" + Thread.currentThread().getName() + ",执行:普通任务");for (int i = 0; i < 3; i++) {scheduledThreadPool.execute(r3);}
}
- 4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务。
public void singleTheadExecutorTest() {ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();for (int i = 0; i < 5; i++) {final int j = i;singleThreadExecutor.execute(() -> out.println("线程:"+Thread.currentThread().getName() + ",执行:" + j));}
}
5. 什么是线程安全问题
- 多线程环境中,且存在数据共享,一个线程访问的共享数据被其它线程修改了,那么就发生了线程安全问题;整个访问过程中,无一共享的数据被其他线程修改,就是线程安全的。
- 程序中如果使用成员变量,且对成员变量进行数据修改,就存现数据共享问题,也就是线程安全问题。
6. Java如何解决线程安全问题
- 使用线程同步机制Lock 锁机制
Lock lock = new ReentrantLock();
lock.lock();
try{
//可能会出现线程安全的操作
}finally{
//释放锁
lock.unlock();
- synchronized 关键字
public synchronized void test01(){//该方法同一时间只能被一个线程访问
}public void test02(String str){System.out.println("111");synchronized (str) {//该区域同一时间只能被一个线程访问}System.out.println("2222");
}
- 消除共享数据:即多个线程数据不共享或者共享的数据不做修改。使用局部变量,不使用成员变量。如果使用成员变量,对成员变量不进行修改。
最后
感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!
相关文章:

WinXP不能共享Win7的打印机的解决方法
现在很多企业里存在着WinXP和Win7混用,WinXP不能正常共享Win7的文件和打印机,经过设置发现Win7可以Ping通Winxp并且也可以发现WinXP的共享文件,可是WinXP却不能共享Win7的文件和打印机,看了一下相关资料后简单设置就解决了这个问题…

第三阶段 10_JavaWeb基础_
因为要准备接本,不一定能够每天更新 转载于:https://www.cnblogs.com/BaiZe258/p/9251075.html

工厂模式(Factory)(转)
先来明确一个问题,那就是有的时候,实例化这个活动不应该总是公开的进行, 也就是不要公开的使用 new 操作符,因为,这样容易造成耦合问题。 我们不应该针对实现编程,但是当我们在使用 new 的时候,…

Asp.net后台创建HTML
为了使HTML界面中的内容能根据数据库中的内容动态显示用户需要的内容,或者根据权限不同要显示同而实现页面内容的动态创建 使用HtmlGenericControl创建HTML标签 引入命名空间: using System.Web.UI.HtmlControls; 更改其属性: hgg_div.Attributes.Add("style&q…

oracle视图(转)
视图的概念 视图是基于一张表或多张表或另外一个视图的逻辑表。视图不同于表,视图本身不包含任何数据。表是实际独立存在的实体,是用于存储数据的基本结构。而视图只是一种定义,对应一个查询语句。视图的数据都来自于某些表,这些…

Redis 事物
redis 事物: Redis 事物的实现: 首先 wath监控键值 myKey开启批量执行 multi,执行命令入列,执行 exec 。如果监控的键值mykey 没有被修改过,则exec 中批量执行的命令成功,否则执行失败。无论执行成功与否&a…
python dos攻击_利用SMB漏洞DoS攻击任何Windows系统
原标题:利用SMB漏洞DoS攻击任何Windows系统近日微软报出SMB V1存在漏洞,安全研究员并将此漏洞称作 “ SMBLoris ”,解释其能够发动拒绝服务(Dos)攻击,可以感染 Windows 2000 及以上操作系统的任一版本 SMB …

java基础编程题(2)
1、给定一个二叉树,找出其最大深度。 注:二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x…

python元组转字典_python中怎么将元组、字典转化为列表
python中将元组、字典转化为列表的方法: python中可以使用list()方法将元组或字典转化为列表: list()方法语法:list( tup ) 参数 tup -- 要转换为列表的元组。 返回值 返回列表。 示例: 将元组转换为列表:#!/usr/bin/p…

搭建Git服务器教程转载
1. 在Windows下使用sshmsysgit客户端搭建Git服务器 http://www.codeproject.com/Articles/296398/Step-by-Step-Setup-Git-Server-on-Windows-with-CopS 2. 在Windows下使用Apachemsysgit客户端搭建Git服务器 http://www.devbean.info/2011/10/apache-git-server-on-windows/ 3…

存储过程处理错误数据
create or replace procedure ERR_REDUCEDATA is --sx --定义变量 v_realindiobjid VARCHAR2(100); v_indiobjid VARCHAR2(32); v_residuemoney number ; v_reducemoney number ; v_approbjid VARCHAR2(32); -- v_indiecoid VARCHAR2(32); --v_indiecocode VARCHAR2(32); v_Ap…
[置顶] 面向业务开发应用
自从计算机出现后,快速便捷的从太平洋一样的文海中找到水滴大小的资料真正成为了可能,而能够帮助人们实现这一愿望的程序员就像中世纪的航海家一样用神秘的代码程序指引着计算机一步一步实现的需求。而他们所用的被称之为“程序”的序列组合,…

vector方法
借鉴网上资料,整理了vector使用的一些方法,记录下来,方便以后查阅 vector初始化 vector<int>a(10) //只定义长度 vector<int>a(10,1)//长度为10,初始值为1 vector<int>a(b); //用b向量来创建a向量,…

MyEclipse Enterprise Workbench 9.0 破解及注册机 注册码
MyEclipse 9.0的激活机制终于破解了,破解步骤比老版本要复杂一些,但是是绝对可以破解的,这个破解对主程序无任何修改,只替换公钥,如果有牛人会快速从公钥反推私钥,那就什么都不用改了,步骤如下&…

python字典一键多值_python字典中如何一键多值的写入?
python字典中如何一键多值的写入? python字典中一键多值写入的方法: 1、循环写入字典key、value、删除指定的键值对: 原文本‘jp_url.txt’每行元素以逗号分隔:host_key,product_id,product_name,cont_start,cont_end ah2.zhangyue.com,10000…

向实现细节低头
本来想搞明白所有的东西,然后自己集成,避免引入额外的组件,避免复杂的维护成本。 现在想想,相比于投入的巨大精力,其收益过小,还是要有所取舍。转载于:https://www.cnblogs.com/youge-OneSQL/p/9268924.htm…

Session丢值的问题
本来本地调试好好的,一上服务器session就非常容易丢失,表现在,用window.href跳转丢session,用httpmoulde丢session,在frame里面ifarme里面丢session,折磨了一天,才知道是因为应用程序池的原因,一个池里面放了太多网站,导致session丢失(系统还没有上线,光放那也不行), 还有应用程…

换发型app任性扣费?苹果app订阅任性扣费?怎么办?刚成功
2019年9月18日17:09:27 什么黑猫举报没用 先关闭订阅 账户中心自助申请试试,不通过再进行下面这步 https://getsupport.apple.com/?callerhome&PRKEYS 技术支持网址 然后就等电话吧,一般10秒钟就打过来了。 告诉原因,提供收费的订单号&a…

用eclipse阅读编辑android和kernel,uboot的源代码
from: http://hi.baidu.com/designhouse/blog/item/ff3f0df4a33571f37709d736.html 1. 用eclipse阅读编辑android源代码的配置方法有官方文档,非常详细,http://source.android.com/source/using-eclipse.html 阅读android代码用的是Eclipse IDE for Jav…

当一个序列满足对于任意的前 项和都满足不小于_时间序列分析第01讲--平稳序列(基本概念,线性平稳序列)...
第一章 平稳序列1.1平稳序列基本概念无论是从原序列中把趋势项去掉得到的随机波动项,还是用随机差分后得到残差序列,都会存在一种现象:随机项会沿着水平值波动,并且前后之间具有相关性,与独立序列不同。一、定义定义1.…

京医通如何删除临时卡,解绑
1、解绑的话,如果你是正式卡或者社保卡,可以在账户里面,点击卡进去详情页,里面会有一个解绑 2、重点就是临时卡了,挂号的时候很恶心。 目前唯一的解决办法就是,注销账户。 1)、解绑所有正式卡 2…

T-SQL查询——详解公用表达式(CTE)
对于Select查询语句来说,通常情况下,为了是T-SQL代码更加简洁和刻度,在一个查询中应用另外的结果集都是通过视图而不是查询进行分解的,但是,视图作为系统对象存储在数据库中,那对于结果集仅仅需要在存储过程…

如何实现显示超过10个字符就显示省略号?
// 要展示的文本(nickName) this.nickName 风一样的女子凤一样的我,有想认识嘛~~ if (this.nickName.length > 10) {this.nickName this.nickName.substring(0, 10) "...";console.log(00, this.nickName)}备注:substring() 方法用于提取…

课程实验代码及动手动脑测试
枚举类型测试代码: public class EnumTest {public static void main(String[] args) {Size s Size.SMALL;Size t Size.LARGE;// s和t引用同一个对象?System.out.println(s t); //// 是原始数据类型吗?System.out.println(s.getClass().is…

python利用自动识别写模块_Python 利用pytesser模块识别图像文字
使用的是python的pytesser模块,原先想做的是图片中文识别,搞了一段时间了,在中文的识别上还是有很多问题,这里做记录分享。 可将图片中的文字转换成文本(主要是英文)。 1.pytesser安装 使用设备:…

C02-程序设计基础提高班(C++)第9周上机任务-类和对象
第9周:阅读教材第8章(p231-262),主要内容是类和对象,学会定义类和对象解决问题,完成第9周上机任务;(回到C02-程序设计基础提高班(C)学习安排)实践任务:【任务…

在不影响配置下,清除netscreen密码
在缺省情况下,设备恢复特征被启用。可通过输入 unset admin device-reset 命令禁用它。同样,如果NetScreen 设备处于 FIPS 模式,恢复特征被自动禁用。1. 在登录提示下,键入设备的序列号。2. 在密码提示下,再次键入序列…

如何删除一个CSDN上自己上传的资源
如何删除一个CSDN上自己上传的资源 第一步,找到你想删除的资源,其URL举例为:http://download.csdn.net/detail/ssergsw/9733040则删除的get请求为:http://download.csdn.net/index.php/user_console/del_my_source/9733040删除成功…

关于计算机中二进制原码,反码,补码的简要解释
原码,补码,反码的概念 正数原码:正数的原码为取绝对值的数转二进制,5的原码为 00000000 00000000 00000000 00000101 负数原码:负数的原码为取绝对值的数转二进制,然后符号位(最高位&a…