21-2 Java 线程的协作
多线程协作的基本机制 wait/notify
多线程之间除了竞争访问同一个资源外,也经常需要相互协作,怎么协作呢?本节就来介绍Java中多线程协作的基本机制 wait/notify
。
wait 实际上做了什么呢?它在等待什么?之前我们说过,每个对象都有一把锁和等待队列,一个线程在进入 synchronized 代码块时,会尝试获取锁,如果获取不到则会把当前线程加入等待队列中,其实,除了用于锁的等待队列,每个对象还有另一个等待队列,表示条件队列,该队列用于线程间的协作。
notify 做的事情就是从条件队列中选一个线程,将其从队列中移除并唤醒,notify 和 notifyAll 的区别是,它会移除条件队列中所有的线程并全部唤醒。
wait/notify 方法只能在 synchronized 代码块内被调用,如果调用 wait/notify 方法时,当前线程没有持有对象锁,会抛出异常 java.lang.IllegalMonitor-StateException。
21-3 Java 线程池
线程是在一个进程中可以执行一系列指令的执行环境,或称运行程序。多线程编程指的是用多个线程并行执行多个任务。当然,JVM 对多线程有良好的支持。
尽管这带来了诸多优势,首当其冲的就是程序性能提高,但多线程编程也有缺点 —— 增加了代码复杂度、同步问题、非预期结果和增加创建线程的开销。这次,我们来了解一下如何使用 Java 线程池来缓解这些问题。
为什么使用线程池?
创建并开启一个线程开销很大。如果我们每次需要执行任务时重复这个步骤,那将会是一笔巨大的性能开销,这也是我们希望通过多线程解决的问题。
为了更好理解创建和开启一个线程的开销,让我们来看一看 JVM 在后台做了哪些事:
- 为线程栈分配内存,保存每个线程方法调用的栈帧。
- 每个栈帧包括本地变量数组、返回值、操作栈和常量池
- 一些 JVM 支持本地方法,也将分配本地方法栈
- 每个线程获得一个程序计数器,标识处理器正在执行哪条指令
- 系统创建本地线程,与 Java 线程对应
- 和线程相关的描述符被添加到 JVM 内部数据结构
- 线程共享堆和方法区
22. Java 正则表达式
正则表达式(regular expression)用于指定字符串的模式,你可以在任何需要定位匹配某种特定模式的字符串的情况下使用正则表达式。
- 大部分字符都可以与它们自身匹配
- . 符号可以匹配任何字符(有可能不包括行终止符,这取决于标志的设置)。
- 使用 \ 作为转义字符,例如,
\\.
匹配句号而\\\
匹配反斜线。 - ^ 和 $ 分别匹配一行的开头和结尾。
- 如果 X 和 Y 是正则表达式,那么
XY
表示“任何 X 的匹配后面跟随 Y 的匹配”,X|Y
表示“任何 X 或 Y 的匹配”。 - 你可以将量词运用到表达式 X:X+(1 个或多个)、X* (0 个或多个)与 X ?(0 个或 1 个)。
- 默认情况下,量词要匹配能够使整个匹配成功的最大可能的重复次数。你可以修改这种行为,方法是使用后缀 ?(使用勉强或吝啬匹配,也就是匹配最小的重复次数)或使用后缀 +(使用占有或贪婪匹配,也就是即使让整个匹配失败,也要匹配最大的重复次数)。
例如,字符串 cab 匹配 [a-z]*ab,但是不匹配 [a-z]*+ab。在第一种情况中,表达式 [a-z]* 只匹配字符 c,使得字符 ab 匹配该模式的剩余部分;但是贪婪版本[a-z]*+ 将匹配字符 cab,模式的剩余部分将无法匹配。 - 我们使用群组来定义子表达式,其中群组用括号 () 括起来。例如,([±]?)([0-9]+)。然后你可以询问模式匹配器,让其返回每个组的匹配,或者用 \n 来引用某个群组,其中 n 是群组号(从 \1 开始)。
- 捕获组可以通过从左到右计算其开括号来编号。
23. Java 图形化编程
图形用户界面(Graphical User Interface,简称 GUI)编程对于某种语言来说非常重要。Java 的应用主要方向是基于 Web 浏览器的应用,用户界面主要是 HTML、CSS 和 JavaScript 等基于 Web 的技术,这些介绍要到 Java EE 阶段才能学习到。
而本章介绍的 Java 图形用户界面技术是基于 Java SE 的 Swing,事实上它们在实际应用中使用不多,因此本章的内容只做了解。
Java 图形用户界面技术
1. AWT
AWT(Abstract Window Toolkit)是抽象窗口工具包,AWT 是 Java 程序提供的建立图形用户界面最基础的工具集。AWT 支持图形用户界面编程的功能包括:用户界面组件(控件)、事件处理模型、图形图像处理(形状和颜色)、字体、布局管理器和本地平台的剪贴板来进行剪切和粘贴等。AWT 是 Applet 和 Swing 技术的基础。
AWT在实际的运行过程中是调用所在平台的图形系统,因此同样一段AWT程序在不同的操作系统平台下运行所看到的样式不同的。
2. Applet
Applet 称为 Java 小应用程序,Applet 基础是 AWT,但它主要嵌入到 HTML 代码中,由浏览器加载和运行,由于存在安全隐患和运行速度慢等问题,已经很少使用了。
3. Swing
Swing 是 Java 主要的图形用户界面技术,Swing 提供跨平台的界面风格,用户可以自定义 Swing 的界面风格。Swing 提供了比 AWT 更完整的组件,引入了许多新的特性。Swing API 是围绕着实现 AWT 各个部分的 API 构筑的。Swing 是由100% 纯 Java 实现的,Swing 组件没有本地代码,不依赖操作系统的支持,这是它与AWT组件的最大区别。本章重点介绍Swing技术。
4. JavaFX
JavaFX 是开发丰富互联网应用程序(Rich Internet Application,缩写RIA)的图形用户界面技术,JavaFX 期望能够在桌面应用的开发领域与 Adobe 公司的 AIR、微软公司的 Silverlight 相竞争。传统的互联网应用程序基于 Web 的,客户端是浏览器。而丰富互联网应用程序试图打造自己的客户端,替代浏览器。
Swing 技术基础
AWT 是 Swing 的基础,Swing 事件处理和布局管理都是依赖于 AWT,AWT 内容来自 java.awt 包,Swing 内容来自 javax.swing 包。AWT 和 Swing 作为图形用户界面技术包括了 4 个主要的概念:组件(Component)、容器(Container)、事件处理和布局管理器(LayoutManager),下面将围绕这些概念展开。