第一章 java多线程
1、实现多线程的方式主要有两种:
继承Thread类(线程类也实现了Runnable接口)
实现Runnable接口
start()方法通知线程规划器,此线程已经准备就绪,等待调用线程对象的run()方法,
这个过程就是让系统安排时间来执行Thread的run()方法,也就是使线程得到运行,启动线程,具有异步执行效果。
如果调用代码thread.run()就不是异步了,而是同步,此线程对象不交给线程规划器进行处理,而是由main主线程调用run()方法,
也就是必须等run()方法中的代码执行完后才执行后面的代码。
***执行start()的顺序不代表线程启动的顺序。
***非线程安全:主要是指多个线程对同一对象中的同一实例变量进行操作时会出现值被更改、值不同步的情况,进行影响程序的执行流程。
当一个线程想要执行synchronized同步中的代码时,会先去尝试获取锁,直到能拿到这把锁为止,程序中有多个线程来争取这把锁。
synchronized可以在任意对象及方法上加锁,加锁的这段代码称为“互斥区”或“临界区”
某些JVM中i--分三步执行
1.取得原有i值
2.计算i-1
3.对i进行赋值
*****在i--的这三个步骤中,如果有多个线程同时访问,那么一定会出现非线程安全问题。
println是线程同步的,但i--操作是在进入println之前进行的,所有可能会非线程安全
1.3 currentThread()方法、
返回代码段正在被哪个线程调用的信息
1.4 isAlive()方法、
判断当前线程是否处于活动状态(活动状态就是线程已经启动且尚未停止,线程正处于运行或准备运行)
在使用isAlive方法时,如果将线程对象以构造参数的形式传递给Thread对象进行start启动时,运行结果是有差异的。
造成差异的原因主要是Thread.currentThread和this的差异。
1.5 sleep()方法、
在指定的毫秒数内,让当前“正在执行的线程”休眠(暂停执行)
正在执行的线程:this.currentThread返回的线程
1.6 getId()方法、
取得线程的唯一标识
1.7 停止线程:interrupt()、
放弃当前的操作:thread.stop方法已经废弃,不建议使用。
此方法不会终止一个正在运行的方法,还需要添加一个判断才可以完成线程的停止。
java中有三种方法可以停止线程:
(1):退出标志,当run执行完成之后完成线程终止。
(2):stop方法强行终止,不安全,已废弃,不建议使用。
(3):interrupt方法。
1.7.1 停止不了的线程、
使用interrupt方法,并不会立即终止线程,只是在当前线程添加了一个线程停止的标记,并不是真正的停止了。
1.7.2 判断线程是否停止、
(1):this.intertupted方法
(2):this.isInterrupted方法
使用Thread.currentThread.intertupted方法可中断线程,但interrupted方法有清楚中断状态的功能,第二次调用为flase
区别:isInterrupted方法不清除中断状态标识。
interrupt() 向当前调用者线程发出中断信号
isinterrupted() 查看当前中断信号是true还是false
interrupted() 是静态方法,查看当前中断信号是true还是false并且清除中断信号,顾名思义interrupted为已经处理中断信号。
注:interrupt()方法发出的中断信号只能被wait() sleep() join()这三个方法捕捉到并产生中断。(目前我所知)
1.7.3 能停止的线程-异常法
如果有异常直接break的话,会终止当前循环,当后面的代码仍然会执行。
异常中断应该抛出一个异常,后续代码不会执行。
1.7.4 在沉睡中停止
sleep状态下,中断线程会进入catch语句,并且清除停止状态值,使之变成false。
先终止线程,再休眠,也会进入catch。
1.7.5 能停止的线程-暴力停止
stop():作废,因为强制性的停止可能会导致一些清理性的工作得不到完成。
对锁定的对象进行了解锁,导致数据得不到同步的处理,出现数据不一致的情况。
1.7.6 stop方法与java.lang.ThreadDeath
调用stop方法会抛出java.lang.ThreadDeath异常,但此异常不需要显示的捕捉。
1.7.7 释放锁的不良后果
造成数据的不一致性
1.7.8 使用return停止线程
interrupt和return结合使用也能实现停止线程的效果。
1.8 暂停线程
暂停线程意味着线程还可以恢复运行,使用suspend暂停线程,使用resume可以恢复线程。
suspend与resume方法的缺点---独占
如果使用不当,极易造成公共的对象独占,使其他线程无法访问公共同步对象。
独占:线程是同步的,当一个对象获取对象锁之后,在同步方法中中断了此线程,线程一直没有恢复,锁一直没有释放,导致其他线程对象无法访问。
suspend与resume方法的缺点---不同步:
容易出现因为线程的暂停而出现数据不同步的现象
1.9 yield方法
放弃当前CPU资源,将它让给其它的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚放弃,就又占用了。
1.10 线程的优先级
操作系统中,线程可以划分优先级,优先级较高的线程获得较多的CPU的资源,也就是优先执行优先级较高的线程对象中的任务。
setPriority()
1.10.1 线程优先级的继承性
例如:A线程启动B线程,则B线程的优先级和A线程是一样的。
1.10.2 优先级具有规则性
高优先级的线程总是大部分先执行完
1.10.3 优先级具有随机性
优先级高的线程不一定先执行完
1.10.4 线程运行快慢
优先级越高,获得CPU资源越多,运行越快
1.10.5 守护线程-daemon
java中有两种线程,一种是用户线程,一种是守护线程。
守护线程是一种特殊的线程,有陪伴的意思,当线程中不存在非守护线程时,守护线程自动销毁。
典型的守护线程就是垃圾回收线程。
守护线程的作用就是为其他线程运行提供便利服务。