在阅读Java线程池ThreadPoolExecutor源码的时候,发现它很巧妙地把线程池状态runState和线程数workCount两个变量存放在了一个int型变量里面。

我们先看一个数值,如下是一个32位int的二进制:

0 0000 0000 0000 0000 0000 0000 0001

1)高位第一位表示符号,0是正数,1是负数

2)高位第二位和第三位表示runState的绝对值(线程池运行状态),runState可取值(-1,0,1,2,3)分别表示(running,shutdown,stop,tidying,terminated)

3)剩下的用来表示线程数workCount,这里表示仅有1个线程,总共可以存储2^29-1个线程,大概5亿个。

如何存储在一个变量?

这样的表示法,把状态和workCount存储在了一个int变量里,那么这个变量是怎么计算出来的呢?

首先,我们先获得runState的值,比如:

int runState = -1

再把runState向左移位29位

-1 << 29

这样就得到了

0 0000 0000 0000 0000 0000 0000 0000

假设现在有3个线程,那么workCount = 3,我们把上面得到得值再加上workCount,即按位或( | )运算,如下

1010 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0011
---------------------------------------
0 0000 0000 0000 0000 0000 0000 0011

上面,我们把runState和workCount存储在一个变量里,接下来我们看看如何把他们拆解开。

如何取到runState?

上面我们得到了一个变量

1010 0000 0000 0000 0000 0000 0000 0011

我们知道32位的二进制中,高位前三位其实就是runState,所以我们去除后面29位的值即可。我们只需要做一个按位与( & )运算

1010 0000 0000 0000 0000 0000 0000 0011
1110 0000 0000 0000 0000 0000 0000 0000
---------------------------------------
0 0000 0000 0000 0000 0000 0000 0000

只需要把结果向右移位29位即可得到runState的值(ThreadPoolExecutor的runState是已经移位以后的值,与本文不同)

如何取到workCount?

后29位就是workCount的值,所以我们去除前3位的值即可。同样我们做一个按位与( & )运算

1010 0000 0000 0000 0000 0000 0000 0011
0001 1111 1111 1111 1111 1111 1111 1111
---------------------------------------
0 0000 0000 0000 0000 0000 0000 0011

ThreadPoolExecutor的runState和workCount变量怎么存储?的更多相关文章

  1. C++变量的存储类别与作用域

    总结一下C++中变量的存储类别以及变量的作用域. (1)标示符的存储类别决定了标示符在内存中存在的时间(我们可以理解标示符就是确定一个变量的符号,也就是我们所说的变量名) 二:存储类别 (1)静态存储 ...

  2. java笔记之变量的存储方式

    1.java变量存储域 java变量的存储区域主要放在以下几个地方: (1)寄存器:可以说是最快的存储区,在C/C++中可以声明寄存器变量,但是在java中不能声明寄存器变量,只是编译器在编译时确定. ...

  3. const变量的存储区及修改权限

    转自const变量的存储区及修改权限 [cpp] view plaincopy const int a = 1; int *p = const_cast<int*>(&a); *p ...

  4. C51变量的存储

    一.全局变量和局部变量 全局变量和局部变量的区别在于作用域的不同.此外还有静态全局变量和静态局部变量. 全局变量作用域为全局,在一个源文件中定义,其他的源文件也可以应用.在其他的源文件中使用exter ...

  5. 你的变量究竟存储在什么地方 && 全局内存

    我相信大家都有过这样的经历,在面试过程中,考官通常会给你一道题目,然后问你某个变量存储在什么地方,在内存中是如何存储的等等一系列问题.不仅仅是在面试中,学校里面的考试也会碰到同样的问题.  如果你还不 ...

  6. c 变量的存储类型auto等(基础知识)和c函数变量

    总结 1).在c语言中每一个变量和函数有两个属性:数据类型和数据的存储类别. 2). 对数据型(如整型.字符型等).存储类别指的是数据在内存中存储的方式. 存储方式分为两大类: 静态存储类和动态存储类 ...

  7. (C/C++学习笔记) 九. 变量的存储类型

    九. 变量的存储类型 ● 变量的存储类型(见附页) ● 注释 ①对于自动变量,它属于动态存储方式. 但是也可以用static定义它为静态自动变量,或称静态局部变量,从而成为静态存储方式.由此看来,一个 ...

  8. C语言变量、函数的作用域及变量的存储方式

    一.变量的作用域和存储方式 在C语言中每个变量都有两种基本属性:数据类型.数据的存储类别. 数据类型很多人都已熟知,例如:字符型(char).整型(int).浮点型(float)等等.存储类别是指数据 ...

  9. c语言 变量的存储类别以及对应的内存分配?

    <h4><strong>1.变量的存储类别</strong></h4>从变量值存在的角度来分,可以分为静态存储方式和动态存储方式.所谓静态存储方式指在程 ...

随机推荐

  1. java -cp 用法介绍

    java -cp 和 -classpath 一样,是指定类运行所依赖其他类的路径,通常是类库,jar包之类,需要全路径到jar包,window上分号“;” 分隔,linux上是分号“:”分隔.不支持通 ...

  2. Android通过adb shell am broadcast发送广播 参数说明

    通过命令行执行adb shell am broadcast发送广播通知. adb shell am broadcast 后面的参数有: <INTENT> specifications in ...

  3. 源码编译vi过程中进行配置时报“checking if compile and link flags for Python are sane... no: PYTHON DISABLED”怎么办?

    答: 需要安装python开发库(如果不安装这个库,那么在配置时执行./configure --enable-pythoninterp=yes将不会生效,以至于vi的python特性并没有被开启) 如 ...

  4. scikit-learn机器学习(四)使用决策树做分类,并画出决策树,随机森林对比

    数据来自 UCI 数据集 匹马印第安人糖尿病数据集 载入数据 # -*- coding: utf-8 -*- import pandas as pd import matplotlib matplot ...

  5. IEnumerable和IQueryable口的区别

    IQueryable: 动态表达式树拼接查询语句,把拼接后查询语句进行执行:Execute触发,延迟加载IEnumerable:对内存中的数据,动态拼接查询语句,进行查询:ToList触发,延迟加载: ...

  6. python中Requests的重试机制

    requests原生支持 import requests from requests.adapters import HTTPAdapter s = requests.Session() # 重试次数 ...

  7. SQL中有关DQL、DML、DDL、DCL的概念与区别?

    SQL(Structure Query Language)结构化查询语言是数据库的核心语言,是高级的非过程化编程语言.它功能强大,效率高,简单易学易维护.SQL语言基本上独立于数据库本身.使用的机器. ...

  8. ffmpeg学习笔记-ffmpeg在VS下的运用

    ffmpeg官网提供了window平台下额开发工具供开发者使用,这篇文章主要以3.2版本的ffmpeg作为演示,记录在VS2013下,怎么去编译ffmpeg 下载 在官网中,按照以下步骤下载 下载Wi ...

  9. spring的控制器如何传递数据到视图

    1.控制器代码 2.传递数据代码 model.addAttribute("name", name); 通过model对象传递

  10. 线上Storm的worker,executor,task参数调优篇

    问题引入: 线上最近的数据量越来越大,出现了数据处理延迟的现象,观察storm ui的各项数据,发现有大量的spout失败的情况,如下: ------------------------------- ...