JAVA 多线程(4)
接着3说:
一、String常量池
先回顾 java 的基本数据类型:
变量就是申请内存来存储值。也就是说,当创建变量的时候,需要在内存中申请空间。
内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据。
因此,通过定义不同类型的变量,可以在内存中储存整数、小数或者字符。
Java语言提供了八种基本类型。六种数字类型(四个整数型(默认是int 型),两个浮点型(默认是double 型)),一种字符类型,还有一种布尔型
说byte之前说一下别的。计算机码或者语言是二进制也就是 0 和1,为了让计算机能识别人类语言,所以用二进制来定义规则,也就是编码,把人类语言翻译为二进制的数据。
所以这里多记一下:
计算机的计算单位-》
0/1 的单位我们称为bit ,也就是虽小单位,1byte = 8bit ,byte 我们称它为字节,比如 10000001 的大小是1byte ,也就是8bit。byte简称为B。
再往上,就是K,1K = 1024B,我们常说的1KB 意思就是说有1K的B,但是K是1024 不是1000 ,因为计算机是通过二进制来识别计算的,这样计算性能更高。
以此类推 1M = 1025K,1G = 1024 M,1T = 1024G 等等等。
多说依据硬盘空间与网络传输单位,为了方便,一般服务商则采用的是十进制来计算,所以有时候我们买的是10G的硬盘,但是计算机上显示的却比它小。第三方网络服务商也是通过十进制而不是二进制。这点需要注意。
数字型(整数)
byte:
- byte数据类型是8位、有符号的,以二进制补码表示的整数;(256个数字),占1字节
- 最小值是-128(-2^7);
- 最大值是127(2^7-1);
- 默认值是0;
- byte类型用在大型数组中节约空间,主要代替整数,因为byte变量占用的空间只有int类型的四分之一;
- 例子:byte a = 100,byte b = -50。
short:
- short数据类型是16位、有符号的以二进制补码表示的整数,占2字节
- 最小值是-32768(-2^15);
- 最大值是32767(2^15 - 1);
- Short数据类型也可以像byte那样节省空间。一个short变量是int型变量所占空间的二分之一;
- 默认值是0;
- 例子:short s = 1000,short r = -20000。
int(一般我们使用int较多):
- int数据类型是32位、有符号的以二进制补码表示的整数;占3字节
- 最小值是-2,147,483,648(-2^31);
- 最大值是2,147,485,647(2^31 - 1);
- 一般地整型变量默认为int类型;
- 默认值是0;
- 例子:int a = 100000, int b = -200000。
long:
- long数据类型是64位、有符号的以二进制补码表示的整数;占4字节
- 最小值是-9,223,372,036,854,775,808(-2^63);
- 最大值是9,223,372,036,854,775,807(2^63 -1);
- 这种类型主要使用在需要比较大整数的系统上;
- 默认值是0L;
- 例子: long a = 100000L,int b = -200000L。
long a=111111111111111111111111(错误,整数型变量默认是int型)
long a=111111111111111111111111L(正确,强制转换)
如果强制为long 请在变量值后加上L
数字型(浮点)
float:
- float数据类型是单精度、32位、符合IEEE 754标准的浮点数;占4字节 -3.4*E38- 3.4*E38。。。浮点数是有舍入误差的
- float在储存大型浮点数组的时候可节省内存空间;
- 默认值是0.0f;
- 浮点数不能用来表示精确的值,如货币;
- 例子:float f1 = 234.5f。
- float f=6.26(错误 浮点数默认类型是double类型)
- float f=6.26F(转换正确,强制)
- double d=4.55(正确)

double:
- double数据类型是双精度、64位、符合IEEE 754标准的浮点数;
- 浮点数的默认类型为double类型;
- double类型同样不能表示精确的值,如货币;
- 默认值是0.0d;
- 例子:double d1 = 123.4。
布尔型
boolean:
- boolean数据类型表示一位的信息;
- 只有两个取值:true和false;
- 这种类型只作为一种标志来记录true/false情况;
- 默认值是false;
- 例子:boolean one = true。
关于布尔型占用几个字节请参考
https://www.jianshu.com/p/2f663dc820d0
引用上面这位博主的话:
boolean: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.
布尔类型:布尔数据类型只有两个可能的值:真和假。使用此数据类型为跟踪真/假条件的简单标记。这种数据类型就表示这一点信息,但是它的“大小”并不是精确定义的。
可以看出,boolean类型没有给出精确的定义,《Java虚拟机规范》给出了4个字节,和boolean数组1个字节的定义,具体还要看虚拟机实现是否按照规范来,所以1个字节、4个字节都是有可能的。这其实是运算效率和存储空间之间的博弈,两者都非常的重要。
字符型
char:
- char类型是一个单一的16位Unicode字符;用 ‘’表示一个字符。。java 内部使用Unicode字符集。。他有一些转义字符 ,2字节
- 最小值是’\u0000’(即为0);
- char数据类型可以储存任何字符;
- 最大值是’\uffff’(即为65,535);可以当整数来用,它的每一个字符都对应一个数字
- 可以存放汉字,字母和数字占一个字节,一个字节8位,中文占2个字节,16位
- char 的值使用单引号 ‘s’
参考地址https://www.cnblogs.com/1130136248wlxk/articles/5105524.html
说完了基本类型,String是什么String是一个类,是引用类型。
重点:
Java为String类型提供了缓冲池机制,当使用双引号定义对象时,Java环境首先去字符串缓冲池寻找内容相同的字符串,如果存在就拿出来使用,否则就创建一个新的字符串放在缓冲池中。
例如: String S=new String("abc''), 产生(或者创建)几个对象?
答案是:产生一个或者两个对象。如果常量池中原来没有“abc",就产两个对象,如果字符串常量池中"abc",就产生一个对象。
因此,这个问题如果换成 String str = new String("abc")涉及到几个String对象?合理的解释是2个。

在Java中,被final修饰的类是不允许被继承的,并且该类中的成员方法都默认为final方法。
在这里要永远记住一点:“String对象一旦被创建就是固定不变的了,对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象”。
字符串常量池:
VM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。
每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串。
其他String的讲解请参考
https://blog.csdn.net/qauchangqingwei/article/details/80831797
所以~ 字符串是具有缓存机制的,多线程中如果使用string最晚lock锁,可能会出现以下问题:
使用不同的锁建立异步机制,但是结果是使用同一个锁:
public static void main(String[] args) {
Test2 test2 = new Test2();
String a;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
test2.judge("A","AA");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
test2.judge("A","BB");
}
});
t.start();
t2.start();
}
public void judge(String what,String param) {
synchronized (what) {
while (true){
System.out.println(param);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出结果:

线程t2 的没有抢到资源,因为同步锁(对象监视器是“A”),线程A和线程B的锁实际上是同一个锁,因为String的缓存机制,“A”在编译器就被放在字符串常量池中,导致实际指向的是同一个对象。
如果使用new String 的方式就没问题了,问new String 实际上会在堆中再创建一个对象。
二、死锁
当程序中出现某一个线程等待一个永远都不会释放的锁时,就会出现死锁。
例如2个线程A和B,调用同一个实例对象的方法C和方法D,方法C和D中使用同步块绑定了对象锁E和F。
或者说有一个锁A,线程A和线程B要用用,但是锁A是永远不会释放~咋整- 死锁。
public static void main(String[] args) {
TestThread testThread = new TestThread();
Thread t = new Thread(testThread,"线程A");
Thread t2 = new Thread(testThread,"线程B");
testThread.setUsername("A");
try {
t.start();
Thread.sleep(100);
testThread.setUsername("B");
t2.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class TestThread implements Runnable {
private String username;
Object a = new Object();
Object b = new Object();
public void setUsername(String username) {
this.username = username;
}
@Override
public void run() {
if (username.equals("A")) {
synchronized (a) {
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b) {
System.out.println("A OVER");
}
}
} else {
synchronized (b) {
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (a) {
System.out.println("B OVER");
}
}
}
}
}
输出:

没有OVER ,线程A在等线程B的对象锁b,线程B在等线程A的对象锁a。
查询:
通过到jdk的bin目录查询状态。


由此监测到了死锁状态。
JAVA 多线程(4)的更多相关文章
- 40个Java多线程问题总结
前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...
- Java多线程基础知识篇
这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程--让主线程等待子线程执行完毕
使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...
- Java多线程 2 线程的生命周期和状态控制
一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...
- java 多线程 1 线程 进程
Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报 分类: javaSE综合知识点(14) 版权声明:本文为博主原创文章,未经博 ...
- 一起阅读《Java多线程编程核心技术》
目录 第一章 Java多线程技能 (待续...)
- 第一章 Java多线程技能
1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...
- java从基础知识(十)java多线程(下)
首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...
随机推荐
- Ubuntu18.04或者Deepin15.8 部署Django项目
一.首先先安装nginx静态服务 1.安装gcc g++的依赖库sudo apt-get install build-essential && sudo apt-get install ...
- soundJs库简单使用心得
概述 由于工作需要,学习了一下soundJs库,把心得记录下来,供以后开发时参考,相信对其他人也有用. soundJs是createJs的一部分,它提供了强大的API来处理音频,是音频类H5的一个比较 ...
- 《机器学习实战(基于scikit-learn和TensorFlow)》第六章内容学习心得
本章讲决策树 决策树,一种多功能且强大的机器学习算法.它实现了分类和回归任务,甚至多输出任务. 决策树的组合就是随机森林. 本章的代码部分不做说明,具体请到我的GitHub上自行获取. 决策树的每个节 ...
- 深入分析Java I/O的工作机制 (一)
此篇博客看至许令波的深入分析javaWeb内幕书籍, 此篇博客写的是自己看完之后理解的重点内容,加一些理解,希望对你有帮助. 1.Java的I/O类库的基本架构 先说一下什么是类库:可以说是类的集合, ...
- [原创]K8Cscan插件之Web主机扫描(存活主机、机器名、Banner、标题)
[原创]K8 Cscan 大型内网渗透自定义扫描器 https://www.cnblogs.com/k8gege/p/10519321.html Cscan简介:何为自定义扫描器?其实也是插件化,但C ...
- JavaScript递归中的作用域问题
需求是这样的,从子节点寻找指定className的父节点,一开始就想到递归(笨!),Dom结构如下: <div class="layer_1"> <div cla ...
- ASP.NET Core 如何在运行Docker容器时指定容器外部端口(docker compose)
前面我写了一系列关于持续集成的文章,最终构建出来的镜像运行之后,应该会发现每次构建运行之后端口都变了,这对于我们来说是十分不方便的,所以我们可以通过修改docker compose的配置文件来完成我们 ...
- C++版 - 剑指offer 面试题16:反转链表(Leetcode 206: Reverse Linked List) 题解
面试题16:反转链表 提交网址: http://www.nowcoder.com/practice/75e878df47f24fdc9dc3e400ec6058ca?tpId=13&tqId= ...
- Bitmap那些事之内存占用计算和加载注意事项
前言:本来我是做电视应用的,但是因为公司要出手机,人员紧张,所以就抽调我去支援一下,谁叫俺是雷锋呢!我做的一个功能就是处理手机中的应用ICON,处理无非就是美化一下,重新与底板进行合成和裁剪,用到了很 ...
- 分析 Oracle SQL 执行计划的关注点
本文内容摘自<剑破冰山--Oracle开发艺术>一书. 1.判定主要矛盾 在遇到复杂 SQL 语句时,执行计划也非常复杂,往往让人分析起来觉得无从下手,此时应避免顺序解决问题,而是快速定位 ...