自定义一个异常类
/*
* 如何自定义异常类?
* 1. 继承于现的异常结构:RuntimeException 、Exception
* 2. 提供全局常量:serialVersionUID
* 3. 提供重载的构造器
*
*/
public class MyException extends Exception{
static final long serialVersionUID = -7034897193246939L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
多线程
一个线程对应一个栈和程序计数器;一个进程对应一个方法区和堆。
项目三
-
代码复用, 当有复用的部分或是可以抽取出来为一个功能而模块化的时候,要抽取出来,提高可读性
-
使用枚举代替一些数字,这样可以方便阅读,同时如果更改数字的时候,不需要更改代码的其他位置。
-
switch中直接使用枚举的变量名;导包时使用static可省略类名(工具、枚举类);
-
重写toString的时候,如果直接使用super会造成不一定调用直接父类的情况,可以另建一个方法,来代替super()的使用。同时和这个方法也是public/继承下来的,可以直接调用
-
数组判空,需要null以及length==0,看具体的情况
创建
方式一:继承于Thread的类
-
创建继承于Thread的子类
-
重写Thread类的run() ;
-
创建Thread类的子类的对象
-
通过此对象调用start() ;两个作用:1.启动当前线程 ; 2. 调用当前线程的run() :
-
不能通过直接调用run() 方法的方式启动线程
-
要创建两个线程,必须要有两个对象,而不能是一个对象start() 两次;
// 创建Thread类的匿名子类的方式
class Test{
public static void main(String[] args) {
new Thread(){
@Override
public void run() {
super.run();
}
}.start();
}
}
yiled() : 释放当前CPU的执行权
join() ; 在线程a中调用线程b的join(),此时线程a进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态
线程的优先级
setPriority(int p) ;
getPriority() ;
-
MAX : 10
-
MIN : 1
-
NORM :5
方式二:
实现Runnable
-
创建一个实现了Runnable 接口的类
-
实现类去实现Runnable中的抽象方法 : run()
-
创建实现类的对象
-
将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
-
通过Thread类的对象调用start();
两种创建方式的对比:
优先选择 : 实现Runnable接口的方式
-
实现的方式没有类的单继承性的局限性。
-
实现的方式更适合来处理多个线程共享数据的情况
联系:Thread 类 也实现了Runable 接口
相同点:两种方式都需要重写run()
线程的生命周期
线程安全
同步代码块
synchronized(同步监视器) {
// 需要被同步的代码
};
说明:操作共享数据的代码,即为需要被同步的代码
共享数据:多个线程共同操作的变量。
同步监视器:俗称,锁;任何一个类的对象,都可以充当锁;
-
要求:多个线程必须要共同用一把锁
补充:
-
在实现Runnable接口创建多线程的方式中,我们可以考虑使用this来充当同步监视器
-
在继承Threaad类创建多线程的方式中,慎用this充当同步监视器,考虑使用当前类充当同步监视器
同步方法
使用同步方法解决继承Thread类的方式的线程安全问题
-
同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。
-
非静态的同步方法,同步监视器是 : this
静态的同步方法,同步监视器是 当前类本身
Lock(锁)
先创建一个 ReentrantLock
lock.lock() ;
lock.unlock() ;
synchronized 与 lock 的异同?
相同:二者都可以解决线程安全问题
不同:synchronized 机制在执行完相应的同步代码以后,自动的释放同步监视器
Lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock())
优先使用顺序:Lock --> 同步代码块(已经进入了方法体,分配了相应的资源) --> 同步方法(在方法体之外)