深入解析Java并发编程:线程安全与线程间通信的基础知识
Java并发编程是一个非常热门的话题,无论是在采访还是在高度场景中。它将涉及与Java并发编程有关的知识。 Java的并发编程有两个主要的基础知识,一个是线程安全性,另一个是线程之间的通信。这个Java并发编程系列博客是一个博客系统,以了解Java并发编程的知识记录。我也希望帮助别人。

概括
1。线程概念
2。Java线程的实现
3。Java线程状态循环简介
4。线程类中常见方法的分析
1。什么是线程
线程是程序执行流的最小单元。标准线程由线程ID,当前指令指针(PC),寄存器集和堆栈组成。另外,该线程是该过程中的实体。它是由系统独立计划并分发的基本单元。线程共享过程拥有的所有资源都可以在同一过程中的多个线程之间同时执行。由于螺纹之间的相互约束,该线程在操作过程中间歇性是间歇性的。线程也准备好,阻止和运行。每个程序至少有一个线程。如果程序只有一个线程,则是程序本身。
2。Java线程实现
Java线程实现有两种类型。第一个是继承线程类,另一个是实现可运行的接口。线程类还实现可运行的接口。可运行的接口仅具有一个Run()方法。
3.Java线程状态
首先查看图片状态循环图。这张照片很重要
1.20人同时访问2张门票窗户。同时,只有两个可以购买门票的人。当其中一个购买门票时,在被占领的窗户上购买了18人之一。
20人相当于20个线程,2人等于资源。当18人在等待时,这等同于线程阻塞。
关键:如何控制统一时间的并发数量是2?
多线程计划设计中有三个同步工具,要求我们掌握,即信号量(信号量),Countdownlatch
信号量是在多线程环境中使用的设施。该设施负责协调各种线程,以确保它们可以正确,合理地使用公共资源,并且它也是操作系统中控制流程的同时且相互排斥的数量。
信号量分为两种类型:单个和多值。前者只能通过一个螺纹获得,后者可以通过几个线程获得。
信号介绍
我们以停车场操作为例来解释信号量的作用。假设停车场只有三个停车位,一开始所有三个停车位都是空的。目前,如果同时有三辆汽车,看到门的人可以让他们进入,然后放下汽车挡住。后来的汽车必须在入口处等待,直到车辆留在停车场。目前,如果有一辆汽车离开停车场,见到那个学到的人后,他打开了汽车并放入。
在此停车场系统中,停车位是公共资源。将每辆车与线程进行比较。看到门的人是信号量的角色。信号量是一个非负整数,这意味着可用的公共资源数量(在上面的示例中,您可以使用休闲停车位(类似于模拟信号))。 e比率),首先检查信号量,如果信号量的价值大于1,则将其减少1,然后占据公共资源。如果信号的值为0,则线程将阻止自身,直到其他线程释放公共资源为止。
在信号方面,我们定义了两个操作:获取(获取)和释放。当线程调用获取操作时,它要么成功获得信号量(信号量减去1),要么继续等待直到线程释放信号量或超时。释放(释放)实际上将信号量的值添加到1,然后唤醒等待线程。
信号量主要用于两个目的,一个用于相互使用多个共享资源,而另一个则由并发线程的数量控制。
源数量信号源代码分析
在Java的包装数据包中,信号量类代表信号。内部信号主要是通过AQS(AbstractQueedSynchronizer)实现的。信号量有两个构造函数。参数允许指示许多许可证,并最终传递给AQ的状态值。该线程在运行时首先获得许可证。如果成功,则许可证将减少1,并且线程正在运行。线程运行时释放许可证。如果许可证为0,即获得故障,则该线程位于aqs等待队列中,则将通过释放许可证的其他线程唤醒。您还可以在创建信号量对象时指定其公平性。通常,通常使用非fair信号量。非FAIR信号量是指在获得许可证时尝试获得许可证,而不必关心需要获得许可证的线程是否位于等待队列中。如果失败,他们将进入列表。公平信号量必须首先检查获得许可时等待队列中是否有线程。
施工功能源代码
//非fair构造函数
公共信号(int允许){
同步=新的nonfairsync(允许);
//通过公平参数确定公平性
公共信号量(int允许,布尔集市){{{
同步=公平?新的Fairsync(许可证):新的Nonfairsync(许可证);
获取源代码
public void acceaire()抛出InteruptException {
同步。
公共最终无效的毫无用处(int arg)
抛出InterruptedException {
ifad.Intrupted())
抛出新的InterruptedException();
if(tryacquireshared(arg)<0)
doacquireshard中断(arg);
最终int int nonnonfiairtryAcquireshard(int caperires){
为了 (;;) {{
int可用= getState();
int剩余=可用-Acquires;
if(剩余<0 ||
compareAndSetState(可用,剩余))
剩余的返回;
可以看出,如果剩下
发布源代码
public void repares(){
sync.releaseshared(1);
公共最终布尔值发行(int arg){
if(tryReleaseshared(arg)){
doreaseshared();
返回true;
返回false;
受保护的最终布尔tryReleaseshared(int releases){{{
为了 (;;) {{
int Current = getState();
int next =电流 +发行;
如果(下一个<电流)//溢出
提出新的错误(“超过最高许可证计数”);
if(comparendSetState(当前,下一个))
返回true;
可以看出,发布许可证是在aqs 1中添加状态的值。然后唤醒第一个节点等待doreaseshared等待队列。可以看出,信号量使用AQS共享模式。等待队列中的第一个节点。如果成功获得了第一个节点,它将唤醒下一个节点,依此类推。
例子
包装javalearning;
导入java.util.random;
导入java.util.concurrent.executorservice;
导入java.util.concurrent.executors;
导入java.util.concurrent.semaphore;
公共类SmaphoredeMo {
私有信号SMP =新信号(3);
prive Random rnd = new Random();
类TaskDemo实现运行{
私有字符串ID;
taskdemo(字符串ID){
this.id = id;
@Override
public void run(){
尝试 {
smp.Acquire();
system.out.println(“ thread” + id +“正在工作”);
thread.sleep(rnd.nextint(1000));
smp.Release();
system.out.println(“ thread” + id +“超过”);
} catch(InterruptedException e){{{
公共静态void main(string [] args){{{
Semaphoremo SmaphoredEmo = new SamaphoredeMo();
//注意我创建的线程池的类型,
executorService se = executors.netCachedThreadPool();
se.submit(SmaphoredeMo.New TaskDemo(“ A”);
se.submit(SmaphoredeMo.New TaskDemo(“ B”);
se.submit(SmaphoredeMo.New TaskDemo(“ C”);
se.submit(SmaphoredeMo.New TaskDemo(“ D”);
se.submit(SmaphoredeMo.New TaskDemo(“ E”);
se.submit(SmaphoredeMo.New TaskDemo(“ F”);
se.shutdown();
运行结果
线程C正在工作
线程B正在工作
线程A正在工作
线程C结束了
线程D正在工作
线B结束了
线程E正在工作
线程A结束了
线程F正在工作
线程D结束了
线程E结束了
线F结束了
可以看出,同时,有三个线程同时执行,也可以将其视为三个公共资源(例如计算机的三个串行端口)。