实习生涯之java基础3
- java异常
所有的java异常的顶层父类是java.lang.Throwable。Throwable下面派生了两个子类:Error和Exception。Error表示严重错误,一般是一些系统错误,程序无法处理,只能终止。Exception又分为运行时异常和非运行时异常,运行时异常又称非检查异常,指的是不需要程序员手动try catch 或者用throws声明要捕获的异常, 一般由java编译器自己捕获,比较常见的运行时异常有NullPointerException,数组越界异常,类型转换异常等。
非运行时异常又称检查异常可以通过try catch或者throws声明抛给上层处理。
2:throws和throw
在定义方法的时候,如果有用throws声明,代表这个方法可能会有异常。在使用的时候,必须使用try catch捕获,否则编译器会报Unhandled exception type Exception,或者在用到这个方法的地方继续使用throws,相当于推卸责任放给上层处理。
throw指的是抛出异常。
3:线程池
为什么要用线程池
在多线程开发中,如果每次对服务器的请求都创建要给新的线程,那么就会导致资源的浪费,特别是线程的执行时间<线程的创建和销毁时间的时候,会导致jvm的效率降低,影响系统性能。有任务来的时候,直接在线程池中取线程来用,可以提高复用性,提高效率。
线程池的组成
任务管理器:负责创建和销毁线程池,加入新任务
工作线程:负责完成任务,在线程池中可以循环使用
任务接口:每个任务必须实现的接口,以供工作线程调度任务的进行,
任务队列:相当于一种对任务的缓冲机制
ThreadPoolExecutor
线程池的核心类,该类可以被实例化,一共有4个构造方法,以参数最多的构造方法为例ThreadPoolExecutor(int,int,long,TimeUnit,BlockingQueue,Thread Factory,RejectedExecutionHandler)
分别代表核心线程数,最大线程数,时间,时间单位,线程队列,线程工程,拒绝策略
(1)核心线程:成为一个核心线程不会比清理,即不受time的影响,
(2)最大线程数:最大线程数除去核心线程,就是非核心线程,这些线程的空闲时间一旦大于最大空闲时间,就会被移除。但是只要处于工作状态,就不会被清除。
(3)阻塞队列:一般用ArrayBlockingQueue,基于数组和LinkedBlockingQueue,基于链表。线程池中的工作线程在这里领取任务
(4)Thread Factory是一个接口,其中有一个方法newThread(),可以实现这个方法来定义线程的名称等等。如果不自定义,可以使用Executors中的默认线程工厂。
(5)拒绝策略:
我们可以试着创建要给类实现ThreadFactory接口,重写newThread方法,在其中定义线程名称
之后创建实现Runnable接口的任务,在run方法中输出当前线程,利用原生ThreadPoolExecutor创建线程池,传入7个参数,观察输出结果。
实际开发中,建议使用上述原生方法创建线程池,另有三种有风险的创建方式:FixThreadPool,CacheThreadPool,SingleThreadExecutor。这三种方式都在Executors工具类中,
实际上这三种方式和原生方式有着紧密的关系。
FixThreadPool:内部return new ThreadPoolExecutor,其中核心线程数和最大线程数一样,最大空闲时间为0,意味着全部都是核心线程,不会被销毁,默认队列采用LinkedBlockingQueue,有内存耗尽的风险,因为这个队列的大小为Integer.MAX_VALUE。
SingleThreadExecutor和FixThreadPool类似,核心线程和最大线程数都为1
CacheThreadPool:没有核心线程,最大核心线程为MAX_VALUE,危害与前两种一样。存活时间为60s。
execute和submit
任务有两种,一种是Runnable类型的无返回值,另一种是Callable类型的有返回值,返回值封装在Future对象中。submit可以提交Runnable类型的任务,Future不仅可以查看任务任务执行结果,还可以查看任务是否执行完毕。
Future<?> submit(Runnable r)
Future<?> submit(Runnable r,结果)//提前确定任务完成的返回结果
Future<?>submit(Callable r)
区别:execute无返回值,submit返回一个Future对象;execute位于Executor中而submit位于ExecutorService;
execute只可以提交Runnable,但是submit可以提交Runnable也可以提交Callable
Future
get方法:这是一个阻塞方法,会获取任务的执行结果,意思就是会获取任务执行结果的线程等到这个任务执行完成之后才会继续往下。
cancel方法:boolean cancel(boolean mayInterruptIfRunning),后面那个参数只会影响正在执行的任务。任务有三种:未执行的任务(在任务队列中),正在执行的任务,执行完成的任务。取消未完成的任务时,如果取消之后调用get方法会引发任务取消异常;已完成的任务无法被取消;对于正在运行的任务,如果调用cancel方法,传入false,他会当作任务被取消了,调用get方法会引发异常,但是任务仍会继续执行;如果传入true,那么任务会自己中断,什么时候中断视相应中断指令的情况决定,即:true比false强制性高
拒绝执行机制
有4种,全部都以内部类的形式存放于ThreadPoolExecutor类中并实现RejectedExecutionHandler接口,该接口只有一个rejectedExecution方法,所有策略的代码都在这个方法里面。
shutdown和shutdownNow
shutdown使用之后不再接受新任务,但是原有的任务会继续执行,不返回任务队列中的任务。
shutdownNow使用时候不再接受新任务,原有任务立即停止,以集合的形式返回队列中的任务,如果有任务是属于停不下来的任务,那么该任务会继续进行,要避免这种情况,需要在任务内部加入判断:if(Thread.isInturrupted)return;