96.什么叫程序
- 所谓“程序”,是一个严格有序的指令集合,程序规定了完成某一任务时,计算机所需做的各种操作,以及这些操作的执行顺序
97.单道程序设计环境
- 单道程序设计环境是指:计算机中除了操作系统之外,只存在一个用户程序,即用户程序独享了整个计算机资源
单道程序有如下特点:
- 资源的独占性:任何时候,位于内存中的程序都可以使用系统中的一切资源,不可能有其他程序与之竞争
- 执行的顺序性:内存中每次只有一个程序,各个程序都是按次序执行的,即做完一个,再做下一个
- 结果的再现性:只要执行环境和初始条件相同,重复执行一个程序,获得的结果是一样的
98.多道程序设计环境
- 多道程序是指:计算机中除了操作系统之外,存在多个用户程序,这些程序同时运行
多道程序设计有如下特点:
- 间断性:由于资源共享和合作,并发程序间相互制约,造成合作执行间断
- 失去封闭性:程序执行受外界影响
- 不可再现性:重复执行时,可能得到不同结果
99.进程的由来
- 一方面为了保证程序“是一个在时间上严格有序的指令集合,是静态的保存在存储介质上”这个概念的原有含义,另一方面为了刻画多个程序共同运行时呈现出的这些特征,在操作系统中,以“程序”为基础,又引入了“进程”这一新的概念
- 通俗点说,为了不破坏“程序”这个词原有的含义,而又能刻画多个程序共同运行时呈现出的新特征,所以引入了进程这一概念;按照大多数教材的说法:“为了使程序能并发执行,且为了对并发执行的程序加以描述”,所以人们引入了进程
100.什么叫进程
- 程序只是一组有序的指令集合,他本身没有运行的含义,他只是一个静态的实体
- 进程是程序在某个数据集上的执行
- 进程是一个动态的实体,它有自己的生命周期,它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤销
101.线程的定义
- 线程是一个程序里的不同执行路径
- 以前所编写的程序,每个程序都有一个入口,一个出口以及一个程序顺序执行的序列,在程序执行过程中的任何指定时刻,都只有单独的执行点
- 事实上,在单个程序内部是可以在同一时刻进行多种运算的,这就是所谓的多线程
- 程序、进程、线程的异同参见操作系统
102.多线程的优势
- 多线程编程简单,效率高(能直接共享数据和资源,多进程不能)
- 适合于开发服务程序(web程序,聊天服务
103.创建一个线程的第一种方法
创建一个继承Thread的类(假定类名为A),并重写Thread类的run方法
- 构造一个A类对象,假定对象名为aa
- 调用aa的start方法(start方法是在Thread继承过来的)
104.注意问题:
- Thread中的start()方法的功能就是创建一个新的线程,并自动调用该线程的run()方法,直接调用run()方法是不会创建一个新的线程
- 执行一个线程实际就是执行该线程的run方法中的代码
- 执行完aa.start()后,并不表示aa所对应的线程就一定会得到执行,aa.start()执行完后只是表示aa线程具有了可以立即被cpu立即执行的资格,但由于想抢占cpu执行的线程很多,cpu不一定会立即执行aa所对应的线程
- 一个Thread对象只能代表一个线程
- 一个Thread对象不能两次调用start()方法,否则会抛出异常
105.创建一个新线程的第二种方法
- 定义一个实现了Runnable接口的类,假定为A
- 创建A类对象aa,代码如下:
- A aa = new A();
- 利用aa构造出一个Thread对象tt
- Thread tt = new Thread(aa)
- 调用tt中的start方法
106.Thread的常用方法
- Public final void setName(String name)
- 设置当前线程的名字
- Public static Thread currentThread()
- 返回当前正在执行的线程对象的引用
- Public final String getName()
- 返回当前线程的名字
107.线程控制的基本方法
108.线程优先级
- Java提供了一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器是按照线程的优先级决定调度哪个线程来执行
- 线程的优先级用数字表示,范围从1-10,一个线程的缺省优先级是5
- Thread.MIN.PRIORITY = 1
- Thread.MAX.PRIORITY = 10
- Thread.NORM.PRIORITY = 5
- 使用下述线方法获得或设置线程对象的优先级
- Int getPriority();
- Void setPriority(int newPriority)
通常高优先级的线程比低优先级的线程先执行,但并不总是这样,因此实际开发中并不单纯依赖优先级来决定线程的执行次序
109.线程的休眠
- 线程休眠——暂停执行当前正在执行的线程,使之进入阻塞状态,待经过指定的“延迟时间”后再醒来并进入到就绪状态
- Thread类提供的相关方法
- Public static void sleep(long millis)
- Public static void sleep(long millis。Int nanos)
- 由于是静态方法,可由类名Thread直接调用
- Sleep()方法会抛出InterruptedException异常,我们必须对其捕捉
110.线程的让步
- 让出CPU,给其它线程执行的机会
- 让运行中的线程主动放弃当前获得的CPU处理机会,但不是使该线程堵塞,而是使之转入就绪状态
- Public static void yield()
111.线程的挂起和恢复
- 线程挂起——暂停当前正在运行的线程,使之进入阻塞状态,并且不会自动恢复运行
- 线程恢复——使得一个已挂起的线程恢复运行
- Thread类提供的相关方法:
- Public final void suspend()
- Public final void resume()
- suspend()方法挂起线程时并不释放其锁定的资源,这可能会影响其他线程的运行,且容易导致线程的死锁,已不提倡使用
112.生命周期控制(Shut)
113.Synchronized关键字
- synchronized可以用来修饰
- 一个方法
- 一个方法内部的某个代码块
114.synchronized修饰代码块
- 格式:
- synchronized(类对象名)// 1行
- {
- 同步代码块 // 3行
- }
- 功能:
- synchronized(类对象名aa)的含义是:判断aa是否已经被其它线程霸占,如果发现已经被其它线程霸占,则当前线程陷入等待中,如果发现aa没有被其它线程霸占,则当前线程霸占aa对象,并执行3行的同步代码块,在当前线程执行3行代码块时,其它线程无法再执行3行的代码块(因为当前线程已经霸占了aa对象),当前线程执行完3行的代码后,会自动释放对aa对象的霸占,此时其它线程会相互竞争对aa的霸占,最终CPU会选择其中一个线程执行
- 最终导致的结果:
- 一个线程在操作某资源的时候,将不再允许其它线程操作该资源,即一次只允许一个线程处理该资源
115.synchronized修饰方法
- synchronized修饰一个方法时,实际霸占的是该方法的this指针所指向的对象
- 即synchronized修饰一个方法时,实际霸占的是正在调用该方法的对象
- 附注:
- 霸占的专业术语叫锁定
- 霸占住的那个对象专业术语叫做监听器
116.同步概念
- 通常,一些同时运行的线程需要共享数据。在这种时候,每个线程就必须要考虑与其它一起共享数据的线程的状态与行为,否则的话就不能保证共享数据的一致性,从而不能保证程序的正确性。
117.同步概念(2)
118.notify和wait方法
- This.notify()
- 功能:
- 不是叫醒正在执行this.notify()的当前线程
- 而是叫醒一个正在wait this对象的其它线程,
- 如果有多个线程正在wait this对象,通常是叫醒最先wait this对象的线程,
- 但具体是叫醒哪一个,这是由系统调度器决定的
119.notify和wait方法(2)
- 假设现在有T1,T2,T3,T4四个线程
- 我们在T4线程中执行了aa.notifty()语句
- 则即便此时T1,T2,T3没有一个线程因为wait aa而陷入阻塞状态,T4线程中执行aa.notify方法时也不会有任何错误
- 本程序就证明了一点
- 执行aa.notify方法时如果一个线程都没有叫醒,这是可以的
120.notify和wait方法的总结
- aa.wait()
- 将执行aa.wait()的当前线程转入阻塞状态,让出CPU的控制权
- 释放对aa的锁定
- aa.notify()
- 假设执行aa.notify()的当前线程为T1
- 如果当前时刻有其他线程因为执行了aa.wait()而陷入阻塞状态,则叫醒其中的一个
- 所谓叫醒某个线程就是令该线程从因为aa.wait而陷入阻塞状态转化为就绪状态
- aa.notifyAll()
- 叫醒其他所有因为执行了aa.wait()而陷入阻塞状态的线程
121.生产消费【经典问题】
- 一个仓库最多容纳6个产品,制造商现在要制造20件产品存入仓库,消费者要从仓库中取出这20件产品来消费
- 制造商制造产品和消费者取出产品的速度很可能是不一样的,编程实现两者的同步
122.要注意的问题
- 执行完20行的代码后,程序不会立即切换到另一个线程
- 20行代码叫醒的是其它线程,叫醒的不是本线程
- 在最开始,P和C刚开始执行时,
即便P没有wait,也可以在C中notify
即便C没有wait,也可以在P中notify
123.组件
- 组件是图形用户界面的基本组成元素,凡是能以图形化方式显示在屏幕上并能够与用户进行交互的对象均为组件,如菜单,标签,文本框
- 组件分类:
- Java.awt.Component
- java.awt.MenuComponent
- 说明:抽象类java.awt.Component是除菜单相关组件之外的所有javaAWT组件类的根父类,该类规定了GUI组件的基本特性,如尺寸、位置和颜色效果等,并实现了作为一个GUI部件所具备的基本功能
124.容器
- 组件通常不能独立地显示出来,必须将组件放到一定的容器中才可以显示出来
- 有一类特殊的组件是专门用来包含其它组件的,这类组件叫容器,java.awt.Container是所有容器的父类,java.awt.Container继承自java.awt.Conponent
- 容器类本身也是个组件,具有组件的所有性质,但反过来组件不一定是容器
125.Frame常用的方法
- Public void setBounds(int x, int y, int width, int height)
- 设置窗体的位置和大小,x和y表示窗体左上角距离屏幕的水平和垂直距离,width和height是窗体本身的宽度和高度
- Public void setSize(int width, int height)
- 设置窗体的大小,width和height是窗体本身的高度和宽度
- Public void setVisible(boolean flag)
- 设置窗体是否可见,true可见,false不可见
- Public void setBackground(color.C)
- 设置窗体的背景色
126.Panel
- panel是容纳其他组件的组件
- panel是容器
- panel不能单独存在,必须得被添加到容器中
- panel类拥有从其父类继承来的
- setBounds(int x, int y, int width, int height)
- setSize(int width, int height)
- setLocation(int x, int y)
- setBackground(Color c)
- setLayout(LayoutManager mgr)等方法
- panel的构造方法为:
- panel()使用默认的FlowLayout类布局管理器初始化
- panel(LayoutManager layout)使用指定的布局管理器初始化、
127.布局管理器
- 容器对其中所包含组件的排列方式,包括组件的位置和大小设定,被称为容器的布局
- 为了使图形用户界面具有良好的平台无关性,Java语言提供了布局管理器来管理容器中的布局,而不建议直接设置组件在容器中的位置和尺寸
- 每个容器都默认有一个布局管理器,当容器需要对某个组件进行定位或判断其大小时,就会自动调用其对应的布局管理器
- 在AWT中,常见的布局管理器:
- BorderLayout
- FlowLayout
- GridLayout
128.FlowLayout布局管理器
- FlowLayout是panel类默认的布局管理器
- FlowLayout布局管理器对组件逐行定位,行内从左到右,一行排满后换行
- 不改变组件的大小,按组件原有尺寸显示组件,可设置不同的组件间距,行距以及对齐方式
- FlowLatout布局管理器默认的对齐方式是居中
129.FlowLayout布局管理器(2)
- new FlowLayout(FlowLayout.RIGHT, 20, 40)
- 右对齐,组件之间水平间隔20个像素,垂直间隔40个像素
- new FlowLayout(FlowLayout.LEFT)
- 左对齐,水平和垂直间距为缺省值(5)
- New FlowLayout()
- 使用缺省的居中对齐方式,水平和垂直间距为缺省值(5)
130.BorderLayout布局管理器
- BorderLayout是Frame类默认的布局管理器
- BorderLayout将整个容器的布局划分为:
- 东
- 西
- 南
- 北
- 中,五个区域,组件只能添加到指定的区域
- 如不指定组件的加入部位,则默认加到CENTER
- 每个区域只能加入一个组件,如加入多个,则先前加入的会被覆盖
131.BorderLayout布局管理器(2)
- BorderLayout型布局管理器尺寸缩放原则:
- 南、北两个区域在水平方向上缩放
- 东、西两个区域在垂直方向上缩放
- 中部可在两个方向上缩放
132.GridLayout布局管理器
- GridLayout型布局管理器将空间划分成规则的矩形网格,每个单元格区域大小相等,组件被添加到每个单元格中,先从左到右填满一行后换行,再从上到下
- 在GridLayout构造方法中指定分割的行数和列数
- 如:GridLayout(3,4)
- GridLayout是以行数为标准的
133.布局管理器总结
- Frame是一个顶级窗口,Frame的缺省布局管理器为BorderLayout
- Panel无法单独显示,必须添加到某个容器中
- Panel的缺省布局管理器为FlowLayout
- 当把Panel作为一个组件加入到某个容器中后,该Panel依然可以有自己的布局管理器
- 使用布局管理器时,布局管理器负责各个组件的大小和位置,因此用户无法在这种情况下设置组件的大小和位置属性,如果试图用Java语言提供的setLocation(),setSize(),setBounds()等方法,则都会被布局管理器所覆盖
- 如果用户确实需要亲自设置组件大小或位置,则应取消该容器的布局管理器,方法为:
- setLayout(null)