多线程 如何停止一个线程
前言这看似一个完全没有意义的问题,但是如果你是从搜索引擎过来的话,那么说明你碰到过这个问题。线程执行完不就退出了,说停止有什么意义?当然有意义,意义在于,一般创建线程后,如果是一次性的线程,执行结束就可以了,不用管它。如果是一个一直需要保持运行,而需要在某一时刻才需要停止的线程,就需要关注线程是如何退出的。
退出方式
退出标志: 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
interrupt: 使用interrupt方法中断线程。
可以但不推荐: 不推荐使用 stop、suspend及resume 方法。stop 相当于电脑断电关机一样,是不安全的方法。
退出标志方式:使用一个标志不控制线程是否需要继续执行。常驻的业务线程当中一般都会写循环,如果不写循环,一句话能搞定的事或者需要调用才执行的事,就没必要再开线程来处理。stop方法已经过时,不推荐使用。
开启多线程时,运行代码通常是循环结构,只要控制住循环,就可以让run方法结束,也就是线程结束。原理:只要循环终止了,线程也就终止了。
1234567891011121314151617public class S ...
RSA 证书加解密通信
思路经常有需要使用安全传输的场景,尤其是在一些泛及资金安全的行业,对数据的传输犹为重视安全性。一般常用的就是对前参的数据进行加密,再到后台进行解密。接口和接口之前的数据也用一样的方式进行加密和解密。
生成公私钥证书
公钥对接口参数明文加密
私钥对接口参数明文解密
通信双方互相持有对方公私钥
如果所有的接口都需要加解密,可以放到拦截器中去统一处理,也可以用注解的方式,控制哪些接口需要加密,哪些接口不需要加密。
生成 RAS 密钥windows 下使用 OpenSSL 工具生成即可,下载后需要解压,然后在 bin 下面打开 OpenSSL,解压是因为生运行后会生成公私钥文件在当前目录下。mac也有一个自带OpenSSL,可以直接用来生成RSA公钥与私钥。
步骤打开iterm2,输入openssl
1.生成私钥
genrsa -out rsa_private_key.pem 1024
2.生成公钥
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
3.生成 PKCS8 格式私钥
pkcs8 -topk8 ...
对象的创建
这里指普通 Java 对象,而非数组 和 Class对象等。
1.创建对象的过程new ---> 到常量池中检查是否存在一个类的符号引用 ---> 如果有,检查这个符号引用代表的类是否已被加载、解析、初始化 ---> 没有,则执行类加载过程。
2.分配对象类加载完毕后,为新生对象分配内存。对象所需内存大小在类加载完成后便完全确定。分配空间。即,从JVM堆中划出一块确定大小的内存空间。
3.分配方法有两种分配方法:
指针碰撞:使用这种方式的前提是,内存是规整的。左边是空闲的空间,右边是已使用的内存空间,用一块,就往左边移一块,就像秤砣在称中间移动一样。
空闲列表内存不规整,此时不能使用指针碰撞。JVM 就需要维护一个列表,记录哪些空间可用并给对象。
堆内存是否规整决定了使用哪种分配方法。而堆是否会规整则由GC是否带有压缩整理功能决定。
4.避免并发操作同一片内存的问题并发时,A线程 拿着指针在为对象分配 0x111111 这片空间,分配动作执行到一半,B线程 也进来了拿着同一个指针在同一个地址上分配空间。这就出现了问题。
解决方案
CAS 配置失败重试的方式保证更 ...
引用级别
引用级别意义:用来标记对角是否可以被回收级别:强 > 软 > 弱 > 虚
1.强引用即一般普通的引用。如果一个对象是强引用,绝对不会被回收,即使内存空间不足也不会被回收,而是抛 OutOfMemoryError 异常使程序终止。
123String str = "abc";List<String> list = new Arraylist<String>();list.add(str);
在list集合里的数据不会释放,即使内存不足也不会
1Object obj = new Object();
//可直接通过obj取得对应的对象 如obj.equels(new Object());而这样 obj对象对后面new Object的一个强引用,只有当obj这个引用被释放之后,对象才会被释放掉,这是经常用到的编码形式。
2.软引用非必须引用,如果空间不足就会被GC回收。换句话说,在内存溢出之前进行回收。只要没有被回收,该对象就可能被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQu ...
Java 堆内存简介
Java 堆 是虚拟机管理的最大的一块内存。是被所有线程所共享的一块内存区域,在虚拟机启动时创建。
分配内存方式所有的实例和数组都在要堆上分配,但是随着JIT编译器的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换优化技术将会导至一些变化,所有的对象都分配在堆上也变得不那么绝对。
Java 堆是垃圾收集器管理的主要区域,也叫CG堆。由于现在收集器基本都爱用分代收集算法,所以Java堆中还可以细分为:新生代 和 老年代。再细致一点的有: Eden 空间、From Survivor 空间、To Survivor 空间等。从内存分配的角度来看,线程共享的Java堆中可能划多个线程私有的分配缓存区。
如何划分与存放内容无关,无论哪个区域,存储的都仍然是对象实例。进一步划分的目的是为了更好的回收内存、或都更快的分配内存。
存放特点Java 堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像磁盘空间。堆的实现,即可固定大小,也可以扩展,通过 -Xms 和 -Xmx 控制。如果堆中没有内存实例分配,并助理堆无法再扩展时,抛出 OutOfMemoryError
Java 虚拟机简单理解
与PC寄存器一样,Java虚拟机栈也是线程私有的。每一个JVM线程都有自己的java虚拟机栈,这个栈与线程同时创建,它的生命周期与线程相同。
1.虚拟机栈的特点“虚拟机栈”描述的是Java方法执行的内存模型:
每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储:局部变量表、操作数栈、动态链接、方法出口等信息。(栈帧我的理解就是一个对象,用来存储信息用)
每一个方法被调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部变量表
存放了8种基本数据 类型
对象引用 类型
returnAddress 类型
除64位 long 和 duble 占2个局部空间外,其余的数据类型只占1个。注意,局部变量表所需的内存空间在编译期间完成分配,所以进入某个方法时,这个方法需要在栈桢中分配多大的空间完全是确定的,在方法运行时是不会改变局部变量表的大小的。
3.虚拟机栈出现异常两种情况
如果线程请求的深度大于虚拟机所允许的深度,将抛出 StackOverflowError 异常;
如果虚拟机进行动态扩展,而扩展时无法申请到足够的内存,则抛出 Out ...
循环引用是否会被回收
前言见过一个问题说,如果java里的对象出现了循环引用,对象会不会被回收。结论是:会。因为 java 的对象存活算法,使用的是可达性分析算法,而不是引用计算法,java中任何一款GC都没有使用过引用计算法。
示例:
1234567891011public static void main(String[] args) throws IOException { A a = new A(); B b = new B(); a.bb = b; b.aa = a; //a = null; //b = null; System.in.read();}
多线程 生产者消费者模式
多生产消费者模式真正的开发环境下,不可能只有两条线程在跑,但是也有特殊情况,就是只需要两条线程来处理。比如一个线程生产,一个线程消费。这是一种线程协作,这种情场景下,生产者 和 消费者会操作同一个共享变量。看到这里的小伙伴应该是对线程的基本用法有一定了解,这里就直接开始明确几个概念
生产者
生产数据的线程,比如产生订单
消费者
处理生产者产生的订单
实际环境中,生产数据的速度要大于消费的速度,这个现象在很多场景中都存在。
共享变量
会被多个线程共同访问的变量
生产者、消费者模式本质是,通过严格控制两个线程的交替执行,来实现一个生产、一个消费的模式,数据存储在共享变量中。
可以再扩展一下,比如常用的MQ,也是一种生产者消费者模式,Producer 生产消费,Consumer消费消息。
主要资源12345678910111213141516171819202122232425262728293031323334/** * @author liukai * @since 2017/2/18. */public class Resource { private bool ...
telnet工具使用
最近刚装的机器,发现没有telnet,手动搞了一把,顺便做下记录。
查看telnet server是否安装
rpm -qa | grep telnet-server
如果没有,则安装
yum install telnet-server -y
开启telnet服务
chkconfig telnet on
启动telnet服务
service xinetd reload
手动方式启动服务编辑telent的配置文件/etc/xinetd.d/telnet 如下:(设置disable = no,也就是开启telnet服务)
重启
service xinetd restart
C-空类型指针
空类型指针malloc 查看底层源码中发现是空类型的指针,空类型的指针可以接收任意类型的指针,但是不能取出指针里的内容,如果要取出内容必须要强转。
1.验证空类型指针,可以接收任意类型指针,但不可以取值1234567void testVoidPoint() { int a = 100; void *p = &a; printf("%x, %x", &a, p); printf("%d", *p); //error: invalid use of void expression getchar();}
2.通过强转取值将值强转成对应的指针类型取出
12345void testVoidPoint2() { int a = 100; void *p = &a; printf("%d", *((int*)(p)));}
3.开辟空间,证明指针即是动态数组1234567891011void testVoidPoint3() ...