Java增强之并发编程

                                  Java增强之并发编程

1 多线程

1.1 进程及线程

程序启动的时候,电脑会把这个程序加载到内存,在内存中需要给当前的程序分配一段的独立运行的空间,这个空间就专门负责这个程序的运行。每个应用程序运行都需要在内存中有自己独立的运行空间,互不影响。进程就是应用程序在内存中的独立空间,负责当前应用程序的运行,负责调度当前程序中的所有运行细节。

线程:位于进程中,负责当前进程中的某个具备独立运行资质的空间,负责程序中具体的某个独功能的运行。一个进程中至少有一个线程,可以并发运行多个线程。多线程之间共享同一个堆空间,每个线程都有自己独立的栈空间

1.2 多线程

在一个进程中,同时开启多个线程,同时去完成某些任务。

一个进程可以并发运行多个线程,提高运行效率。

1.3 多线程运行的原理

CPU在线程中做时间片的切换。程序的运行时CPU负责的,其实CPU在运行程序时,某个时刻只能运行一个程序,CPU在多个程序之间进行高速的切换,因为切换的频率和速度太快了,所以我们是看不出来的。从而得知多线程虽然可以提高程序的运行效率,但是不能无限制的开线程。

1.4 实现线程的方式

(1)继承Thread类

(2)实现Runnable接口

(3)Callable和FutureTask创建线程

(4)通过线程池创建线程

代码演示见之前的文章:https://blog.csdn.net/weixin_43786255/article/details/92065717

1.5 线程状态图解

详细讲解见:https://blog.csdn.net/weixin_43786255/article/details/92065717

2 java同步关键字

在多线程编程中,为了达到线程安全的目的,往往通过加锁的方式来实现。

2.1 synchronized

是JVM级别的锁,在编译过程中,在指令级别加入一些标识来实现。无法中断正在阻塞队列或者等待队列的线程。synchronize是java语言的内置特性,锁的释放是由jvm决定的,人工无法干预 。

常与wait(),notify(),notifyAll()方法联用,调用wait()方法线程让出CPU,释放锁,进入等待状态waitting,进入等待队列。当其他线程调用notify()(随机唤醒等待队列中的一个线程)或notifyAll()(唤醒等待队列中的全部线程)时没会将队列中的线程对象,放入第二个阻塞队列,状态是blocked,等待锁被释放后,开始竞争锁。

synchronize提供了偏向锁,轻量级锁,重量级锁。

锁的释放时机有两种情况:

           ①获取锁的线程操作完成,该线程会自动释放锁 ;②)获取锁的线程出现异常,jvm会自动释放。

synchronized存在的问题 :

           ①如果获取锁标记的线程不主动释放锁,则未获取标记的只能等待,而且人工无法干预;②当多个线程读写文件时,读读操作互相不影响,但是synchronized仍然无法同时执行。

2.2 Lock

Lock锁是Java代码级别的,用户可以主动添加锁,但是必须手动释放锁。因此一般来说,使用 Lock 必须在 try{}catch{}块中进行,并且将释放锁的操作放在 finally 块中进行,以保证锁一定被被释放,防止死锁的发生。提供了公平锁,轮询锁,定时锁,可中断锁等,还增加了多路通知机制(Condition),可以用一个锁来管理多个同步块。

与synchronized的区别:

           ①synchronized 是 Java 语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;

           ②synchronized 由系统自动释放,lock必须手动释放,否则可能产生死锁。

常见方法如下:

void lock()获取锁(阻塞,如果其他线程获取到锁,需要等待)
boolean tryLock()获取锁(非阻塞,如果其他线程获取到锁,则返回false)
boolean tryLock(long time, TimeUnit unit)获取锁(在指定的时间范围内获取,超时返回false)
void lockInterruptibly()可中断锁
void unlock()释放锁

ReentrantLock 类是唯一实现了Lock 接口的类,并且 ReentrantLock 提供了更多的方法。

区别对待读、写的操作用ReadWriteLock接口的实现类ReentrantReadWriteLock 里面提供了很多丰富的方法,不过最主要的有两个方法:readLock()和 writeLock()用来获取读锁和写锁。

ReadWriteLock将读写操作分离处理:

           ①一个线程获取读锁,另外的线程可以获取读锁。但是不能获取写锁(必须等待读锁释放)。

                      ②一个线程获取写锁,那么一定要等待该线程释放写锁,其他线程才能执行读写操作。

2.3 死锁

死锁:两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,会让程序挂起无法完成任务。

产生死锁的条件:

          ①互斥条件:一个资源每次只能被一个进程使用;

          ②请求与保持条件:一个进程因请求资源而阻塞式,对已获得的资源保持不放;

          ③不剥夺条件:进程已获得的资源,在未使用完成之前,不能强制剥夺;

          ④循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

如何避免死锁:避免相互等待,设置标记位

死锁处理:破坏条件

2.4 Volatile特殊域变量

首先了解在多线程编程中,要解决的问题主要有以下三方面:

            ①原子性:作为一个整体运行

            ②可见性:多个线程修改的内容是可见的。CPU不是直接和系统内存通信,而是把变量读到内部的缓冲,也叫私               有的数据工作栈,修改也是在内部缓存中,但是何时修改到系统内存不能确定,这个时间差就可能导致读到的值不是最新             值。

            ③指令重排:虚拟机把代码编译成指令后,出于优化,保证代码不变的情况下,会调整指令的执行顺序

valotile能够满足可见性和有序性,但无法保证原子性。

            ①保证可见性:在修改后强行把对变量的修改同步到系统内存中,当其他CPu在读取自己内部缓存中的值发现是                volatile修饰的时候会把内部缓存中的值置为无效,从系统内存中读取。

            ②保证有序性:在某些指令中插入屏障指令,用于确保在向屏障指令后面继续执行的时候,前面的所有指令已经                输入完毕。

原子性通过原子量:Atomicxxx:原子量保证数据的原子性

 

2.5 ThreadLocal线程变量副本

ThreadLocal提供了线程本地变量,访问本地变量的每个线程都会拷贝一个变量到自己的本地内存,多个线程操作这个变量的时候,实际上是操作自己本地内存里面的变量,这样就不会对其他线程产生影响。

ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题,ThreadLocal采用以时间换空间的方式,同步机制采用以空间换时间的方式

作用:保证线程的独立变量。

应用场景:有变量或对象实例需要在线程中多个地方被重复使用,不希望线程之间共享,又不希望每次使用是都重新创建,加大内存开销。

与Synchronized的区别:Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。

使用:可以将可以将 ThreadLoad<T>视为 Map<Thread ,T>,把需要隔离的数据放入ThreadLocal,通过threadLocal.set(val)赋值,threadLocal.get()获取值,最好不要放在线程池中,避免复用。

 

3 并发包

3.1 java并发包

jdk1.5版本以后,大多数的特性在 java.util.concurrent 包中,是专门用于多线程发编程的,充分利用了现代多处理器和多核心系统的功能以编写大规模并发应用程序。主要包含原子量、并发集合、同步器、可重入锁,并对线程池的构造提供了强力
的支持。

3.2 线程池

通过重用现有的线程池,而不是创建新的线程,可以在处理多个请求的时候分摊在线程创建和销毁过程中产生的巨大开销,当请求到达的时候工作线程已经存在,不会由于等待创建线程而延迟执行,从而提高系统的响应性。

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

corePoolSize: 核心池的大小(常驻线程数)
maximumPoolSize: 最大的线程数(任务数)
keepAliveTime: 线程空闲的等待时间
unit:等待时间的单位
workQueue: 并发的等待队列(如果任务数超过核心池的大小,任务需要在队列中等待,有界/无界)
factory: 线程工厂,创建线程
handler: 任务拒绝的策略(队列中的任务数和核心池的任务数超过总的max/任务数超过核心池+有界队列中的数目)

ThreadPoolExecutor的执行顺序:

           ①当线程数小于核心线程数时,创建线程

           ②当线程数大于核心线程数,且队列未满时,将任务放入任务队列

           ③当线程数大于核心线程数时,且队列任务已满,若线程数小于最大线程数(核心线程数+有界队列的数目),则创建线程;若线程数大于最大线程数,则抛出异常,拒绝任务。

更多详细讲解见:https://blog.csdn.net/weixin_43786255/article/details/92065717

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473877.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 732. 我的日程安排表 III(差分思想)

文章目录1. 题目2. 解题1. 题目 实现一个 MyCalendar 类来存放你的日程安排&#xff0c;你可以一直添加新的日程安排。 MyCalendar 有一个 book(int start, int end)方法。它意味着在start到end时间内增加一个日程安排&#xff0c;注意&#xff0c;这里的时间是半开区间&…

4.聚合aggregate

聚合(aggregate)主要用于计算数据&#xff0c;类似sql中的sum()、avg() 语法&#xff1a;db.集合名称.aggregate({管道:{表达式}}) 管道 管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的输入 ps ajx | grep mongo 常用管道 $group&#xff1a;将集合中的…

WebView退出时停止视频播放

网上比较流行的方法: 在activity的onPause函数中调用webview的onPause函数。 弊端:视频虽然停止播放但是还是在从网上加载数据(观察流量统计); 比较好的方法: 在activity的onPause函数中调用webview的onPause函数。 在activity的onDestroy函数中webview.loadUrl("file:///…

5.MongoDB索引

mongodb支持索引&#xff0c;以提升查询速度 步骤一&#xff1a;创建大量数据 在命令行中执行如下代码&#xff0c;向集合中插入10万条文档 注意&#xff1a;不要在图形界面中执行&#xff0c;因为软件原因无法插入10万条数据就会中断执行 for(i0;i<100000;i){ db.t1.in…

Hadoop学习之整体介绍及环境搭建

Hadoop学习之整体介绍及环境搭建 1 大数据概述 1.1 什么是大数据 数据(data)是事实或观察的结果&#xff0c;是对客观事物的逻辑归纳&#xff0c;是用于表示客观事物的未经加 工的的原始素材。 大数据&#xff1a;传统处理方式无法解决的不仅大而且复杂的数据集的存储和计算…

05.序列模型 W2.自然语言处理与词嵌入

文章目录1. 词汇表征2. 使用词嵌入3. 词嵌入的特性4. 嵌入矩阵5. 学习词嵌入6. Word2Vec7. 负采样8. GloVe 词向量9. 情感分类10. 词嵌入除偏作业参考&#xff1a;吴恩达视频课深度学习笔记自然语言处理与词嵌入 Natural Language Processing and Word Embeddings 1. 词汇表征…

sql获取总列数

Select count(*) from syscolumns where object_name(id)表名可以获取表的列数转载于:https://www.cnblogs.com/haoqi/p/3388171.html

6.MongoDB备份与恢复

备份 语法 mongodump -h dbhost -d dbname -o dbdirectory -h&#xff1a;服务器地址&#xff0c;也可以指定端口号 -d&#xff1a;需要备份的数据库名称 -o&#xff1a;备份的数据存放位置&#xff0c;此目录中存放着备份出来的数据 例1 sudo mkdir test1bak sudo mongodump…

Hadoop学习之HDFS

Hadoop学习之HDFS 1 HDFS相关概念 1.1 设计思路 分散存储&#xff0c;冗余备份。 分散存储&#xff1a;大文件被切割成小文件&#xff0c;使用分而治之的思想让多个服务器对同一个文件进行联合管理&#xff1b; 冗余备份&#xff1a;每个小文件做冗余备份&#xff0c;并且…

LeetCode 799. 香槟塔(DP动态规划)

文章目录1. 题目2. 解题1. 题目 我们把玻璃杯摆成金字塔的形状&#xff0c;其中第一层有1个玻璃杯&#xff0c;第二层有2个&#xff0c;依次类推到第100层&#xff0c;每个玻璃杯(250ml)将盛有香槟。 从顶层的第一个玻璃杯开始倾倒一些香槟&#xff0c;当顶层的杯子满了&…

C语言进行CGI程序设计

一、CGI概述CGI(公用网关接口)规定了Web服务器调用其他可执行程序(CGI程序)的接口协议标准。Web服务器通过调用CGI程序实现和Web浏览器的交互,也就是CGI程序接受Web浏览器发送给Web服务器的信息,进行处理,将响应结果再回送给Web服务器及Web浏览器。CGI程序一般完成Web网页中表单…

7.MongoDB与python交互

引入模块pymongo from pymongoimport * 主要提供如下对象用于进行交互 MongoClient对象&#xff1a;用于与MongoDB服务器建立连接 DataBase对象&#xff1a;对应着MongoDB中的数据库 Collection对象&#xff1a;对应着MongoDB中的集合 Cursor对象&#xff1a;查询方法find()返…

天池在线编程 2020国庆八天乐 - 7 进制

文章目录1. 题目2. 解题1. 题目 https://tianchi.aliyun.com/oj/118289365933779217/122647324212270017 Given an integer, return its base 7 string representation. 输入范围为[-1e7, 1e7] 。 示例 样例 1: 输入: num 100 输出: 202样例 2: 输入: num -7 输出: -102.…

Hadoop学习之MapReduce

Hadoop学习之MapReduce 目录 Hadoop学习之MapReduce 1 MapReduce简介 1.1 什么是MapReduce 1.2 MapReduce的作用 1.3 MapReduce的运行方式 2 MapReduce的运行机制 2.1 相关进程 2.2 MapReduce的编程套路 2.3 MapTask的并行度 2.4 切片及其源码解读 2.5 ReduceTask的…

四款常见数据库比较同步软件汇总

前言&#xff1a; 目前&#xff0c;数据库技术在各行各业的应用正在逐步加深&#xff0c;在这些应用中普遍采用分布式系统结构。而数据库同步技术是分布式数据库系统中应用非常广泛的一种技术。分 布式数据库系统由多个通过网络连接的数据库组成&#xff0c;它们通常有主从服务…

8.账户管理(非数据库管理人员理解篇

超级管理员 为了更加安全的访问 mongodb,需要访问者提供用户名和密码,于是需要在mongodb 中创建用户 采用了角色-用户-数据库的安全管理方式 常用的的系统角色有: root: 只在 admin 数据中可使用,超级账户,超级权限 Read: 允许用户读取指定的数据库 readWrite: 允许用户读写指…

Hadoop学习之yarn

Hadoop学习之YARN 1 YARN简介 1.1 概述 YARN &#xff08;Yet Another Resource Negotiator&#xff09;是一个资源调度平台&#xff0c;负责为运算程序提供服务器运算资源&#xff0c;相当于一个分布式的操作系统平台&#xff0c;而 MapReduce 等运算程序则相当于运行于操作…

poj1308

#include<stdio.h>#include<string.h>//判断是否有环&#xff0c;判断是否是一个根节点。判断空树的情况#define N 1000000int pre[N10],dis[N10],degree[N10];int find(int n) {return pre[n]npre[n]?n:find(pre[n]);}int main() {int a,b,cnt,flag,f1,f2,i,min,…

天池在线编程 2020国庆八天乐 - 8. 分糖果

文章目录1. 题目2. 解题1. 题目 https://tianchi.aliyun.com/oj/118289365933779217/122647324212270016 描述&#xff1a; 给定长度为偶数的整数数组&#xff0c;该数组中不同的数字代表不同种类的糖果&#xff0c; 每个数字表示一种糖果。 您需要将这些糖果平均分配给弟弟和…

1.Redis简介与基本命令

Redis是一个高性能的key-value存储系统。和Memcached类似&#xff0c;它支持存储的value类型相对更多&#xff0c;包括string(字符串)、list(链表)、set(集合)、zset(sortedset--有序集合)和hash&#xff08;哈希类型&#xff09;。 配置 绑定ip&#xff1a;如果需要远程访问&…