一、多线程间通信/协作方式
wait/notify/notifyAll:
wait/notify/notifyAll是Object类里面的方法,需在synchronized块中调用,用于阻塞/唤醒线程,并且会释放synchronized锁对象;
Object lock = new Object();
synchronized(lock){
lock.wait();//阻塞当前线程,并释放lock对象锁
}
//....
synchronized(lock){
lock.notify();//唤醒lock,并释放lock对象锁
//lock.notifyAll();
}
join/interrupted
join:是Thread类里的方法,在线程A里调用线程B的join方法时会阻塞线程A,直到线程B执行结束,才会唤醒A(实现原理:threadB.join()方法里实际时调用了threadB.wait(),threadB run()执行结束后会自动调用threadB.notifyAll());
interrupted:是Thread类里的方法,该方法调用时会将thread线程的中断标记字段设置为true,但是并不会真的中断线程,而是需要程序员自己在run方法里实现中断逻辑,如果这个线程wait()、join()、sleep()方法而阻塞过程中被打断(interupt),会抛出Interrupte dException;
yeild/sleep
是Thread类里的静态本地方法,yeild意思是让线程让出cpu执行权重新进入cpu竞争序列,sleep则是阻塞线程指定的时间,时间到了后会自动被唤醒,sleep阻塞时已经获取到的synchronized锁不会被释放;
volatile关键字
二、线程的创建方式
1、继承Thread类,重写run方法
2、实现Runable接口,结合Thread类启动线程
3、实现Callable接口,结合TaskFutrue类(本质上还是实现了Runable接口,run方法里调用Callable接口的call方法,利用unsafe包类(LockSupport)实现阻塞主线程直到子线程结束,实现主线程获取子线程的返回值)
4、线程池(ThreadPoolExecutor)核心参数:核心线程数、最大线程数、非核心线程存活时间、阻塞队列、拒绝策略;
//阻塞队列 无界/有界
BlockingQueue blockingQueue = new LinkedBlockingDeque(5);
//自定义拒绝策略
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler()
{
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("拒绝策略执行! ");
r.run();
}
};
//拒绝策略 调用主线程执行/直接决绝/抛异常/删掉队列头的线程立马执行当前线程
RejectedExecutionHandler discardPolicy = new ThreadPoolExecutor.CallerRunsPolicy();
//核心线程数量 最大线程数量 超过核心线程数量时进入阻塞队列,超过阻塞队列(有界)最大限制时 执行拒绝策略
ThreadPoolExecutor tpe = new ThreadPoolExecutor(5,10,20,TimeUnit.SECONDS,blockingQueue,rejectedExecutionHandler);
for(int i=0;i<20;i++){
tpe.execute(new Worker(obj[i]));
//Future ft = tpe.submit(new Worker(obj[i]));
System.out.println("getPoolSize:"+tpe.getPoolSize()+"----queue size:"+tpe.getQueue().size());
}
- 线程池可以通过方法submit()或者excute()提交任务到线程池,方法submit()方式可以像callable接口一样返回线程结果,
- 初始线程中线程数为0或者可以设置初始线程数量
- 当池中的线程数量超过“核心线程数”时,新任务会进入阻塞队列,
- 阻塞队列可以选择有界或者无界队列,若为有界队列,则当队列满了时,线程池会创建非核心线程去执行新提交的任务,
- 当创建的线程数超过”最大线程数“时,新任务将被拒绝策略拒绝,拒绝策略可自定义:如直接决绝新任务、抛出异常、让主线程去执行该任务、删除阻塞队列头的任务然后执行当前任务。