java线程

并行:同时进行操作

并发:多线程进行,但由cpu确定不同时间段哪个线程的继续执行。

  1. 多线程

1.1     多线程创建方式:继承Thread,实现Runnable,实现Callable

①   继承Thread,重写run方法

②   实现Runnable,重写run方法,使用Thread类进行包装

③   实现Callable,重写call方法,使用FutureTask包装,包装成Thread

三者的比较:

Thread: 继承方式, 不建议使用, 因为Java是单继承的,继承了Thread就没办法继承其它类了,不够灵活

Runnable: 实现接口,比Thread类更加灵活,没有单继承的限制

Callable: Thread和Runnable都是重写的run()方法并且没有返回值,Callable是重写的call()方法并且有返回值并可以借助FutureTask类来判断线程是否已经执行完毕或者取消线程执行

当线程不需要返回值时使用Runnable,需要返回值时就使用Callable,一般情况下不直接把线程体代码放到Thread类中,一般通过Thread类来启动线程

Thread类是实现Runnable,Callable封装成FutureTask,FutureTask实现RunnableFuture,RunnableFuture继承Runnable,所以Callable也算是一种Runnable,所以三种实现方式本质上都是Runnable实现

1.2     线程的状态:创建状态(new对象),就绪状态(start后,),运行状态(获得cpu的时间片段),阻塞状态(线程挂起,时间片段结束),死亡状态(run结束,发生异常),锁池状态(寻找锁,释放cpu时间片段,找到就返回就绪状态,)

1.3     获得当前的线程:Thread.currentThread()

1.4     start和run方法:start是将线程进入就绪状态,run是线程运行状态运行的代码

1.5     sleep() 与 interrupt():sleep将进程进入阻塞状态,并释放时间片段,但不会进行释放锁,sleep结束后,将携带返回就绪状态;interrupt(): 唤醒正在睡眠的程序,调用interrupt()方法,会使得sleep()方法抛出InterruptedException异常,当sleep()方法抛出异常就中断了sleep的方法,从而让程序继续运行下去

1.6     wait() 与 notify()notifyall:全部是object的final修饰的方法,不能进行重写。Wait让进程进入阻塞状态,并且释放锁,一直等到被其他线程notify或者notifyall唤醒,如果当前线程不是锁的持有者,会抛出异常。注意:必须写在synchronized方法内部或者synchronized块内部,wait和notify必须注意通知的对象。Interrupt方法属于Thread的,执行不需要获取锁,会抛出异常。Interrupt只会在对处于阻塞状态的线程抛出异常。

1.7     join方法,使当前线程加入父线程,父线程进入阻塞状态,类似于插队

1.8     用户线程:主线程停止也不会受到影响,

守护线程,如果主线程死亡,守护线程一样会死亡。

  1. 线程池

2.1      

 

 

 

 

 

    public ThreadPoolExecutor(int corePoolSize,

                                 int maximumPoolSize,

                                 long keepAliveTime,

                                 TimeUnit unit,

                                BlockingQueue<Runnable> workQueue,

                                 ThreadFactory threadFactory,

                               RejectedExecutionHandler handler)

corePoolSize线程池维持线程最少数量;

maximumPoolSize线程池维持线程最大数量;

keepAliveTime 线程池中空闲时存活的时间;

unit 时间单位

workQueue 存放任务的列表

threadFactory 线程工厂,用来创建新线程

handler 超出线程范围和队列容量而执行的处理策略

 

执行顺序

1.如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

 

2. 如果此时线程池中的数量大于等于corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。

 

3. 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理添加的任务。

 

4. 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

 

5. 当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

 

2.2     常用线程池

1. newCachedThreadPool —— 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

2.newFixedThreadPool —— 创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

3.newSingleThreadExecutor —— 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

4.newScheduleThreadPool —— 创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行

posted @ 2020-08-18 21:29  飞独破  阅读(28)  评论(0)    收藏  举报