异常,线程
一.异常
	  1.什么是异常
		    java程序中出现的不正常显现
	  2.异常的继承体系
		    面向对象语言中异常就是用类来表示
		    (万物皆对象)每个异常都是一个对象
			   异常的根类:Throwable
				      子类1:Error,被称为错误类(操作系统本身有错误,程序员不能避免)------内存溢出,系统崩溃
				      子类2:Exception,被称为异常类
	  3.异常类中常用的三个方法
		    -public void printStackTrace();//打印异常的详细信息
			      包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。
		    -public String getMessage();//获取发生异常的原因
			      提示给用户的时候,就提示错误原因
		    -public String toString();//获取异常的类型和异常描述信息(不用)
	  4.异常的分类:
		    i.编译时异常
			      编译时如果异常出现就会报错
			      是Exception本身以及子类(RuntimeException除外)
		    ii.运行时异常
			      编译时不报错,运行时报错
			      就是RuntimeException本身以及它的子类
	  5.异常产生过程
		    JVM发现了一个异常,数组做大下标是2,但是我们要访问3
		    创建一个异常对象(代表这种异常)
			      new ArrayIndexOutOfBounds(3)
		    把这个异常对象抛出去(不管)
			      throw new ArrayIndexOutOfBounds(3)
		    最终又到了:JVM
			    JVM拿到异常对象之后:
				    处理异常:终端处理
					        立刻停止程序
					        把异常对象的所有信息打印到控制台。
		 列举出常见的三个运行时异常:
			    ArrayIndexOutOfBoundsException 数组下标越界(运行时)
			    NullPointerException 空指针引用异常
			    ClassCastException	类型强制转换异常
				        Animal an=new Dog();//new Cat();
				        Cat cc=(Cat)an;
			    ParseException 编译时异常
			
			====================================================
			
			    IllegalArgumentException - 传递非法参数异常。
			    ArithmeticException - 算术运算异常
			    ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
			    NegativeArraySizeException - 创建一个大小为负数的数组错误异常
			    NumberFormatException - 数字格式异常
			    SecurityException - 安全异常
			    UnsupportedOperationException - 不支持的操作异常
		    注意:
			      JVM默认处理异常的机制:终断处理
二.异常处理
	  1.抛出异常关键字throw
		    throw作用:抛出异常对象(动词)
		    throw格式:
			      throw new XxxException(异常的信息)
	  2.Objects类中提供的非空判断方式:
		    只要我们定义的方法,有引用类型作用参数,那么第一件必须是判空
		    public static<T> requireNonNull(T obj)检查指定的对象引用不是null。
	  3.遇到异常的2种处理方式*******************
		    throws声明抛出异常(不处理)
			      使用格式:
				        public 返回值类型 方法名() throws XxxException{
					        //内部可能会抛出异常
				         }
			      作用:给方法做声明,告诉该方法的调用者,这个方法内部可能抛出某种异常,要求调用者自己处理
		    try.catch捕获异常
			      格式:
				        try{
					          可能出现异常的代码
				        }catch(XxxException e){//捕获异常时,必须是可能抛出异常的类型 或者 其父类类型
					          //处理异常
					        e.printStackStrace();
				        }
				          //下面代码可以照常运行
	  4.【扩展1】catch代码块中三种常见的处理方式
		      a.直接打印 调用 异常对象.printStackTrace();
		      b.记录日志(Log4J ---log for java)
		      c.转成其他异常继续抛出
	  5.【扩展2】多个异常如何捕获处理
			    try{
				      可能出现异常的代码
				      假设:可能出现 异常1,异常2,异常3
					      异常1 继承了 异常2
					      异常3和 异常1 异常2 没有直接关系
			     }
			    a.换个异常  挨个处理
				      try{
					      代码段1(可能出现异常1)
				      }catch(异常1 e){
				
				      }
				      try{
					      代码段2(可能出现异常2)
				      }catch(异常2 e){
				
				      }
				      ..........
			    b.比较标准的处理方式:
				      所有异常一起try,多个catch
				      try{
					        可能出现异常的代码
				      }catch(异常1 e){
				
				      }catch(异常2 e){
				
				      }catch(异常3 e){
				
				      }
				    如果多个异常之间没有子父类关系,那么顺序随意
				    如果其中两个异常有子父类关系,那么保证子类异常写前面,父类异常写后面,或者只写父类异常。
			   e.开发中最常用的:
				    所有异常一起try,一个catch
				      try{
					      可能出现异常的代码
				      }catch(Exception e){
					      此处异常应该写三个异常的共同父类,如果不知道那么直接写Exception
					
				      }
	  6.finally代码块
		      finally:最终的,最后的
		      和try..catch一起使用
		      格式:	
			        try{
				          可能有异常的代码
			        }catch(异常类型 变量名){
				          处理异常的代码
			        }fimally{
				          必须执行的代码
				          一般用来写 释放资源的代码
				          如果没有资源需要释放,那么可以省略finally代码块
			        }
	  7.异常的注意事项:
		       编译时异常需要编译阶段处理,运行时异常编译阶段不需要管它
		       如果父类的方法抛出了多个异常,子类覆盖父类方法时,只能抛出相同的异常或者是他的子集
		       如果父类的方法没有抛出异常,子类也必须不能抛出异常
		       当多异常处理时,捕获处理,前边的类不能是后边类的父类
		       不要在finally里边写return
		       finally可写可不写,通常有资源需要释放时,写finally保证资源正常释放。
三.自定义异常
	  1.为什么要定义异常
		      JDK中指定义一些常用的异常类,实际开发中很可能某些异常是JDK考虑不带
		      所有我们需要自己定义一些异常类
	  2.自定义异常的步骤
		      a.创建一个异常类,但是异常类必须以eaception结尾
		      b.该异常类必须继承Exception 或者  RuntimeException
		      c.自定义的异常类必须是包含里两个构造(无参+String异常信息)
	  3.自定义异常的练习(代码演示)
		    要求:
			      我们模拟注册操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已经被注册。
/**
    * 自定义的异常类
    */
    //1.必须以Exception结尾
    public class MyException extends RuntimeException{
    //2.至少有有两个构造
    //无参构造
    public MyException(){}
    //带有String参数的构造
    public MyException(String info){
    super(info);
    }
    }
测试:
    public static void main(String[] args) {
        //注册
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入您要注册的用户名");
        String next = scanner.next();
        //调用方法注册
        try {
            register(next);
            System.out.println("恭喜您注册成功");
        }catch (MyException e){
            e.printStackTrace();
        }
    }
    //注册方法
    public static void register(String username) throws MyException{
        //判断用户名是否重复
        //1.定义一个集合,模拟数据库
        ArrayList<String> usernames=new ArrayList<String>();
        //添加几个已经存在的用户
        Collections.addAll(usernames,"jake","bill","rose");
        //2.判断用户名是否重复
        if (usernames.contains(username)) {
            //如果用户名已经存在
            throw new MyException("亲,该用户名已经被注册");
        }
    }
四.多线程
	  1.并行和并发:
			      并行:指的两个事件同同一时刻进行
			      并发:指的是两个时间同一时间段内进行
			      宏观:我们人看到的
			      微观:具体的时间片段
	   2.进程和线程:
			      进程:正在运行的程序,就称为进程
			      线程:进程中的某一个任务,就称为线程
			      进程和线程的一些区别(了解)
				        进程是拥有(堆空间和栈空间)独立的空间(不同的之间是不能相互访问数据的),每个进程至少有一个线程
				        线程是在进程中执行的某个任务,可以访问进行的共享数据。一个进程各种多个线程共享堆空间,栈空间是独立的,线程消耗的资源比进程小的多。
			      线程调度:
				        就是指CPU快速地在多个线程间进行切换
				        CPU是单核的:那么这个CPU的某个时刻只能运行一个线程。
				        因为CPU可以快速地在多个线程间,进行快速切换。
			      CPU的两种调度:
				        分时调度:
					            按照时间片,多个线程轮流拥有CPU的执行权
				        抢占式调度:
					            CPU在多个线程之间进行随机分配(跟线程的优先级有关)
				        java中使用抢占式调度,所有Java中多个线程的运行也是随机的
	  3.创建新的线程方式***********
		    当我们运行java程序时,java程序就变成java进程
			    其中至少有两条线程,一个main线程,一条JC(java的垃圾回收器)线程
		    创建新的线程的方式一:
			        描述:一个是将一个类声明为一个Thread的子类
				        这个子类应该重写run类的方法,然后可以分配并启动子类的实例
			    步骤:
				       创建子类 extends Thread
				      重写Thread类中的run方法(就是线程“main”方法,写的就是子线程的任务代码)
				      创建子类的对象(在main里边写)
				      启动子线程 子类.start()
			    代码:
				      子线程:
public class Childthread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("子线程");
}
}
}
主线程:
public static void main(String[] args) {
Childthread childthread = new Childthread();
//childthread.run(); 当使用run时,就是普通方法的调用,先执行完再往下执行。
childthread.start();
for (int i = 0; i < 50; i++) {
System.out.println("主线程iiiiiiiii");
}
}
   注:
		    堆空间是有垃圾回收器
	
	
	
	
原文:https://www.cnblogs.com/linlin1211/p/10295952.html