Java的线程池分好多种:
固定尺寸的线程池、单任务线程池、 可变尺寸连接池、延迟连接池、单任务延迟连接池、自定义线程池
固定大小的线程池
Thread thread = new Thread(() -> { System.out.println(123); }); ExecutorService threadPool = Executors.newFixedThreadPool(10); threadPool.execute(thread); threadPool.shutdown();
- 线程池中,线程用完后是要全部回收的,再用要重新分配。
- 完成了对线程对象的重用,避免了重复创建线程对象造成的资源浪费
- 关闭线程池后,不可以再添加新的线程到池当中,再加就会报错
单任务线程池
可变尺寸的线程池
延迟线程池
- 当当前线程池资源****被占用****,延迟线程顺延排队执行
b.如果资源没有被占用,则加入到批次中
c.延迟线程一样需要竞争资源
单任务延迟线程池
自定义线程池
三者之间的关系:
1.如果没有空闲的线程执行该任务且当前运行的线程数少于corePoolSize,则添加新的线程执行该任务。
2.如果没有空闲的线程执行该任务且当前的线程数等于corePoolSize同时workQueue未满,则将任务入workQueue,而不添加新的线程。
3.如果没有空闲的线程执行该任务且workQueue已满同时池中的线程数小于maximumPoolSize,则创建新的线程执行任务。
4.如果没有空闲的线程执行该任务且workQueue已满同时池中的线程数等于maximumPoolSize,则根据构造函数中的handler指定的策略来拒绝新的任务。
有返回值的线程
1.实现了Callable接口
2.任何线程必须join到Callable之后才会执行
3.应用场景:当当前线程需要前一个线程的执行结果,才能继续执行时,需要get()结果
4.如果不需要返回值,则其和普通线程没有任何区别
线程池-锁
读写锁:
1.场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源;但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写的操作了。
2.三种特性:
1.选择性:支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平。
2.重进入:读锁和写锁都支持线程重进入。
3.锁降级:遵循获取写锁、获取读锁再释放写锁的次序,写锁能够降级成为读锁。
线程池-信号量:
Semaphore semaphore = new Semaphore(10); semaphore.acquire(1); semaphore.release(1);
线程池-阻塞队列:
线程池-阻塞栈:
条件变量:条件变量是针对锁的调度
class A { private Lock lock = new ReentrantLock(); Condition c1 = lock.newCondition(); void test1() throws InterruptedException { lock.lock(); System.out.println("等待开始"); c1.await(); System.out.println("等待结束"); lock.unlock(); } void test2() { lock.lock(); c1.notifyAll(); System.out.println("已唤醒"); lock.unlock(); } }
1.在持锁的情况下,可以等待和唤醒
2.可以实现多对象同时唤醒
原子量:所谓的原子量即操作变量的操作是“原子的”,该操作不可再分,因此是线程安全的。
1.AtomicInteger原子量常用方法:
2.AtomicIntegerArray原子量常用方法
- 即便是原子量,依然要做线程同步
- 保证多个线程对同一个数据的可见性和线程安全性
障碍器: