(二)Java并行程序基础


本节是《Java高并发程序设计》第二章的读书笔记,为尊重原创,需要详细阅读的建议购买原著。

2.1 线程和进程

1、进程是操作系统调度资源分配和调度的基本单位,进程相当于线程的容器,线程是轻量级进程,是程序执行的最小单位,使用多线程并行,是因为线程比进程的切换和调度的成本低。
2、线程的生命周期,
new创建线程,start()后,线程进入runnable状态,没有获得临界区资源进入BLOCKED阻塞状态,调用wait()等方法,进入waiting状态,等待某个预期状态出现后重新回到runnable,调用sleep()等方法,进入TIME_WATING状态,时间片用完或异常报错,进入TERMINATED状态。

2.2 初始线程

2.2.1 新建线程

1、继承Thread类,重写run方法,使用start()调用线程的run()
2、实现Runnable,可以用匿名内部类,实现run方法,将Runnable接口传入Thead的构造函数,因为Thread中有一个传入接口的构造函数,会调用接口的run方法,使用start()调用线程的run()。

2.2.2 线程中断

1、如果出现了wait()或sleep()方法,需要用Thread的中断函数

Thread.interrupt()	//中断线程,置标志位为true
Thread.isInterrupted()	//判断是否中断
Thread.interrupter()	//判断是否中断,并清除当前中断中断状态

使用sleep()或wait()方法时遇到中断会抛出checked异常,需要捕获此异常,设置Thread.interrupt()中断状态,通过代码中Thread.isInterrupted()检查中断状态来判断中断。

2.2.3 等待(wait)和通知(notify)

1、wait和notify是属于object方法的,二者都必须在sychronized代码块中使用,因为调用前必须要获取监控对象(monitor)。
2、wait()方法调用后,线程进入wait等待队列,notify()是随机唤醒从等待队列唤醒线程,notifyAll()是唤醒所有。
3、wait()方法调用后会释放所有的锁,保证其他线程能不被阻塞继续执行。sleep不释放锁。

2.2.4 挂起(suspend)和继续执行(resume)线程

1、suspend挂起后,不会释放锁,直到遇到resume()后线程才会继续执行,如果resume()在suspend()方法前执行了,那么系统可能工作异常,因此,这两个方法已经被丢弃。

2.2.5 等待线程结束(join)和谦让(yield)

1、join有两个方法

public final void join() throws InterruptedException
public final synchronized void join(long mills) throws InterruptedException

第一个方法是无限等待,直到目标线程执行完成
第二个方法是到指定时间后,线程继续执行
2、join的底层原理
本质也是调用了wait(),在目标线程执行完成后,调用notifyAll()唤醒所有的线程,因此,不要在Thread对象使用wait和notify等方法,避免引起API工作异常。
3、yield()是让线程让出CPU,但是让出后,同样会加入线程竞争。

2.3 volatile关键字

1、volatile保证了可见性、有序性和原子性
2、可见性和有序性不再赘述。
3、原子性可以理解为是sychronized的轻量级线程,不能保证复合操作和线程的原子性。
4、能避免重排序。

2.4 线程组

ThreadGroup tg = new ThreadGroup("PrintGroup");

1、将功能相同的线程放在一个线程中统一的管理,如使用activeCout()方法,stop()注意和Thread.stop()一样,可能会有数据不一致问题,list()方法等
2、注意的是,创建线程和线程组的命名要尽可能便于理解。

2.5 守护线程

1、用户线程是系统工作的线程,守护线程只有在守护对象结束,才退出。
2、设置守护线程,要在start()前

Thread t = new DaemonT();
t.setDaemon(true);

Java中线程的优先级是1-10,线程.setPriority(优先级),设置线程优先级。

2.6 sychronized关键字

1、使用方法,可以用于对象,实例方法,或者静态方法,代码段
2、加锁对象、方法和代码段的原理(略)
3、给静态方法加锁,本质是给当前的类加锁,因此,可访问实例的非静态方法。
4、注意的是,在创建线程中,要注意使用同一把锁。
5、sychronized保证原子性、可见性、有序性(因为每次只有一个线程执行,因此,只要保证串行化语意就能保证执行结果的一致,因此,有序性并不能防止指令重排序,和volatile不同)。
补充:
synchronized有两种形式上锁,一个是对方法上锁,一个是构造同步代码块。他们的底层实现其实都一样,在进入同步代码之前先获取锁,获取到锁之后锁的计数器+1,同步代码执行完锁的计数器-1,如果获取失败就阻塞式等待锁的释放。只是他们在同步块识别方式上有所不一样,从class字节码文件可以表现出来,一个是通过方法flags标志,一个是monitorenter和monitorexit指令操作。

2.7 隐蔽的错误

1、使用线程不安全的容器,如:ArrayList、HashMap等。
2、使用Integer对象i作为锁对象,如果出现i++,则会因为i++会创建Integer对象,将引用赋值给i,导致加锁对象出现不一致。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值