第二章-java并行程序基础

2.1 有关线程你必须知道的事 29

进程是线程的容器,进程是程序的实体。

程序是“死”的,进程是“活”的。

线程就是轻量级进程,是程序执行的最小单位。线程间的切换和调度的成本远远小于进程。

2.2 初始线程:线程的基本操作 32

Java中为线程操作提供了一些API。

2.2.1 新建线程 32

通过new关键字创建一个线程对象,此时线程处于NEW状态,等到线程start()方法被调用时,会让这个线程的run方法执行,线程执行时处于RUNNABLE状态,表示线程所需一切资源都准备好了。

2.2.2 终止线程 34

使用stop()方法可以将线程终止,已被废弃可能引起数据不一致性,不推荐使用。

2.2.3 线程中断 38

线程中断并不会使线程立即退出,而是给线程发送一个通知,线程间接收到通知后如何处理,由目标线程自行决定。

三个与线程相关的方法:

intertupt()中断线程(发送通知),isInterrupted()判断线程是否被中断,interrupted()判断是否被中断并清除当前中断标志的状态。

2.2.4 等待(wait)和通知(notify) 41

wait()方法被调用以后,当前线程在这个对象上等待,notify()方法调用会从等待队列中随机唤醒一个线程,这两个方法都属于object类,这两个方法的使用必须包含在synchronized语句中,都得先获得对象监视器。

wait()方法和sleep()方法的区别:wait方法可以被唤起,sleep不能。wait方法会释放目标对象的锁,sleep方法不释放任何资源。

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

suspend挂起方法使线程暂停的同时不会释放任何资源,直到进行resume操作才能使挂起的线程继续,这两个方法已经被废弃不推荐使用。

2.2.6 等待线程结束(join)和谦让(yeild) 49

一个线程的输入可能依赖于另一个线程或多个线程的输出,需要等待依赖线程执行完毕,才能继续执行,join()阻塞在当前线程,直到目标线程执行完毕。

Thread.yeild() 方法是一个静态方法,一旦执行,会使当前线程让出CPU。但其之后还会重新参与CPU资源的争夺。

2.3 volatile与Java内存模型(JMM) 50

当用volatile(易变的,不稳定的)关键字声明一个变量时,就等于告诉虚拟机,这个变量极有可能被某些程序或者线程修改。为了确保这个变量被修改后,所有线程都能“看到”这个改动,虚拟机就必须保证这个变量的可见性等特点。

注意:volatile无法保证一些复合操作的原子性(例如:i++)

2.4 分门别类的管理:线程组 53

  • 线程组:如果线程数量很多可以将具有相同功能的线程放在同一个线程组中。可以使用Thread的构造函数,指定线程所属的线程组ThreadGroup,将线程和线程组关联起来。
  • activeCount():获取活动线程的总数是一个估计值。
  • list():显示线程组的详细信息。

2.5 驻守后台:守护线程(Daemon) 54

守护线程是一种特殊的线程,在后台完成一些系统性的服务。例如:垃圾回收线程,JIT线程等。相对应的是用户线程,当一个Java应用内只有守护线程时Java虚拟机将自动退出。

2.6 先做重要的事:线程优先级 56

在Java中,使用1到10表示线程优先级,数字越大优先级越高。使用setPriority()方法对线程进行设置,高优先级的线程倾向于更快的完成。

2.7 线程安全的概念与关键字synchronized 57

并行程序开发的一大关注重点就是线程安全。一般来说,程序并行化是为了获得更高的执行效率,但前提是,高效率不能以牺牲正确性为代价。线程安全是并行程序的根基

synchronized的作用:实现线程间的同步,它的工作是对同步代码块加锁,使每一次只有一个线程进入同步代码块,从而保证线程的安全性。

关键字synchronized的用法:

  • 指定加锁对象:对给定的对象加锁,进入同步代码之前要获得给定对象的锁
  • 直接作用于实例对象:相当于对当前实例加锁,在进入同步代码块前要获得当前实例的锁。
  • 直接作用于静态方法:相当于对当前类加锁,在进入同步代码块之前要获得当前类的锁。

除了用于线程同步、确保线程安全外,关键字synchronized还可以保证线程间的可见性和有序性。可见性显而易见。就有序性而言,关键字synchronized限制的多个线程是串行执行的,因此保证了有序性。

2.8 程序中的幽灵:隐蔽的错误 61

幽灵:程序出错终止执行,没有什么提示,是最头疼的。

2.8.1 无提示的错误案例 62

求平均值,但是int范围溢出。

2.8.2 并发下的ArrayList 63

ArrayList 是一个线程不安全的容器。如果在多线程中使用ArrayList,可能会导致程序出错。改进的方法很简单,使用线程安全的Vector代替ArrayList即可。

2.8.3 并发下诡异的HashMap 64

并发下的HashMap会导致死循环。最简单的解决方案就是使用ConcurrentHashMap代替HashMap。

2.8.4 初学者常见的问题:错误的加锁 67

Integer i;

i++的本质是创建一个新的Integer对象,并将它的引用赋值给i。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值