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多线程(下)
首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...
随机推荐
- Android JNI 学习(十):String Operations Api & Other Apis
一.String Operations(字符串操作) 1. NewString jstring NewString(JNIEnv *env, const jchar *unicodeChars, js ...
- ubuntu18.04LTS设置静态IP
ubuntu18.04LTS设置静态IP 因为Ubuntu18.04采用的是netplan来管理network.所以在/etc/netplan/目录下有一个以yaml结尾的文件.比如01-networ ...
- [Swift]SwiftyJSON的使用:解析JSON
用法 初始化Initialization import SwiftyJSON let json = JSON(data: dataFromNetworking) 或者 let json = JSON( ...
- Python的基础语法(一)
0. 前言 最近正在重新整理Python的基础知识,以便更好地学习新知识.这一部分主要是讲述Python基础语法的演示.下面的语法都是基于Python3的语法. 1. 注释 注释:Python的注释方 ...
- Source Qualifter组件中sqlquery过长导致截取
问题:Source Qualifter组件中sqlquery过长导致截取原因:Source Qualifter组件中sqlquery可以接受的最长字符数是32767个字符,超过这个数字会导致截取解决方 ...
- 使用 DryIoc 替换 Abp 的 DI 框架
一.背景 你说我 Castle Windsor 库用得好好的,为啥要大费周章的替换成 DryIoc 库呢?那就是性能,DryIoc 是一款优秀而且轻量级的 DI 框架,整个项目代码就两个文件,加起来代 ...
- 解决关于 vue项目中 点击按钮路由多了个问号
问题描述: 在vue项目开发过程中,点击按钮结果页面刷新了一遍 后来发现路径变成了 localhost:8080/?#/login 原因: 这里是 form 表单,点击了button 按钮,触发了他的 ...
- 微软新动向之Android和IOS应用 visual studio 2015 Cordova[原创]
自萨蒂亚·纳德拉(Satya Nadella)上任微软CEO以来,可谓是惊喜不断,仿佛让世界尤其是我们.net程序员心中又燃起了希望.先是免费提供 iOS 版和安卓版 Office:然后在 xbox ...
- 一篇文章让你成为 NIO 大师 - MyCAT通信模型
这篇文章没有详细介绍 NIO 的概念,对于 NIO 不了解的同学,可根据自己需要,阅读这篇介绍 NIO 的博客 io.mycat.net.NIOAcceptor NIOAcceptor负责处理客 ...
- SpringBoot(10) Servlet3.0的注解:自定义原生Servlet、自定义原生Listener
一.自定义原生Servlet 1.启动类里面增加注解 @ServletComponentScan 2.Servlet上添加注解 @WebServlet(name = "userServle ...