Day25
25.01 单例设计模式
单例(单个实例即单个对象)设计模式:保证类在内存中只有一个对象
如果保证类在内存中只有一个对象呢?
1、控制类的创建,不让其他类来创建本类的对象。Private
2、在本类中定义一个本类的对象。Singleton s
3、提供公共的访问方式 public static SingletongetInstance(){return s}
单例写法两种:
1、饿汉式 开发用这种方式
25.02 Runtime类
单例设计模式的应用场景:
Runtime类是一个单例类,私有构造方法,对外提供访问Runtime方法。属于lang包下。可以执行DOS命令
25.03 Timer
Timer类:计时器
一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。
TimerTask Date
25.04 两个线程间的通信
1、什么时候需要通信
多个线程并发执行时,在默认情况下CPU是随机切换线程的
如果我们希望他们有规律的执行,就可以使用通信,例如每隔线程执行一次打印
2、怎么通信
如果希望线程等待,就调用wait
如果希望唤醒等待的线程,就调用notify
这两个方法必须在同步代码中执行,并且使用同步锁对象来调用
wait和notify都是Object的方法
25.05 三个或三个以上间的线程通信
多个线程通信的问题
notify()方法是随机唤醒一个线程
notifyAll()方法是唤醒所有线程
JDK1.5之前无法唤醒指定的一个线程
如果多个线程之间通信,需要使用notifyAll通知所有线程,用while来反复判断条件
下面是1.5版本之前的做法
线程间的通信注意的问题:
1、在同步代码块中用哪个对象调用锁,就用哪个对象调用wait和notify等方法;
2、为什么wait和notify方法定义在Object类中?因为锁对象可以是任意对象,而Object是所有类的基类(超类),所以wait和notify需要定义在Object这个类中
3、sleep和wait方法的区别?
区别1:首先sleep方法必须传入参数,即时间值,时间到了自动醒来。而wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入就是直接进入等待状态。
区别2:sleep方法在同步函数或同步代码块中,不释放锁,即睡着了也抱着锁睡,在指定时间可以自己醒来。wait方法在同步函数或者同步代码块中释放锁,因为如果不释放锁(即释放执行权),所有线程都在等着。
25.06 JDK1.5的新特性互斥锁
1、同步 效率会比1.5版本之前的好一些
使用ReentrantLock类的lock和unlock方法进行同步。替代synchronized
2、通信
Condition是一个接口,里面的await和signal替代了wait和notify
使用ReentrantLock类的newCondition方法可以获取Condition对象
需要等待的时候使用Condition的await方法, 唤醒的时候用signal方法
不同的线程使用不同的Condition,这样就能区分唤醒的时候找那个线程
25.07 线程组的概述和使用
1、线程组概述
Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制
默认情况下,所有的线程都属于主线程组
public final ThreadGroupgetThreadGroup()//通过线程对象获取它所属的组
public final StringgetName()//通过线程组对象获取它组的名字
我们也可以给线程设置分组
1、ThreadGroup(Stringname)创建线程组对象并给其赋值名字
2、创建线程对象
3、Thrad(ThreadGroup?group,Runnable?targer,String? name)
4、设置整组的优先级或者守护线程
2、案例演示
线程组的使用,默认是主线程组
5.09 线程池的概述和使用
1、线程池的概述
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存周期很短的线程时,更应该考虑使用线程池。线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。在JDK5之前,我们必须手动实现自己的线程池,从5开始,Java内置支持线程池。
2、内置线程池的使用概述
JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newFixedThreadPool(int nThreads)
public staticExecutorService newSingleThreadExecutor()
这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。ExecutorService提供了如下方法
Future>submit(Runnable task)
使用步骤:
创建线程池对象
创建Runnable实例
提交Runnable实例
关闭线程池
3、案例演示
提交的是Runnable
25.10 多线程程序实现的第三种方式(了解)
提交的Callable
Callable是一个接口
25.11 设计模式(简单工厂模式概述和使用)
1、简单工厂模式概述
又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例
2、优点
客户端不需要再负责对象的创建,从而明确了各个类的职责
3、缺点
这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护
4、案例演示
动物抽象类:public abstract Animal{public abstract void eat();}
具体狗类:public class Dog extendsAnimal() {}
具体狗类:public class Cat extendsAnimal() {}
开始,在测试类中每个具体的内容自己创建对象,但是,创建对象的工作如果比较麻烦,就需要有人专门做这个事情,所有就知道了一个专门的类来创建对象。
25.12 工厂方法模式的概述和使用
1、工厂方法模式概述
工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现
就是创建针对的对象,有其针对的工厂
2、优点
客户端不需要再负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强了系统的扩展性
3、缺点
需要额外的编写代码,增加了工作量
4、案例演示
5.13 GUI如何创建一个窗口并显示
1、Graphical User Interface(图形用户接口)
25.14 GUI布局管理器
FlowLayout流式布局管理器
从左到右的顺序排列
Panel默认的布局管理器
BorderLayout边界布局管理器
东南西北中
Frame默认的布局管理器
GridLayout卡片布局管理器
选项卡
GridBagLayout网格包布局管理器
非规则的矩阵
监听事件:满足某种条件就去执行某种方法
25.18 动作监听
ActionListener就一个方法,就不需要Adapter适配器了,直接new对象就可以重写方法就可以了
此处的动作监听默认对的是鼠标左键和空格键,只要这两个动作都可以执行其中的方法
25.19 设计模式(适配器设计模式)
1、什么是适配器
在使用监听器的时候,需要定义一个类事件监听器接口
通常接口中有多个方法,而程序中不一定所有的都用得到,但又必须重写,这很繁琐。
适配器简化了这些操作,我们定义监听器时只要继承适配器,然后重写需要的方法即可。
2、适配器原理
适配器就是一个抽象类,实现了监听器接口,所有抽象方法都重写了,但方法内全都是空的
适配器类需要定义成抽象的,因为创建该类对象,调用空方法是没有意义的,所以就不让创建适配器对象
目的就是为了简化程序员的操作,定义监听器时继承适配器,只重写需要的方法就可以了
25.20 GUI需要知道的
事件处理:
事件:用户的一个操作:点鼠标,敲键盘等
事件源:被操作的组件:按钮等就是事件源
监听器:一个自定义类的对象,实现了监听器接口,包含事件处理方法,把监听源添加在事件源上,当事件发生的时候虚拟机就会自动调用监听器中的事件处理方法。