读写锁
独占锁:一次只能被一个线程占有
共享锁。多个线程可以同时占有
class Apple{ public static void main(String[] args) { Mycache mycache=new Mycache(); for (int i = 0; i <5 ; i++) { final int temp=i; new Thread(()->{ mycache.put(temp+"",temp); }).start(); } for (int i = 0; i <5 ; i++) { final int temp=i; new Thread(()->{ mycache.get(temp+""); }).start(); } } } /*自定义缓存*/ class Mycache{ private volatile Map<String ,Object> map=new HashMap<>(); //读写所 private ReentrantReadWriteLock lock=new ReentrantReadWriteLock(); //存 取的时候 只希望同时只有一个线程写入 public void put(String key,Object value){ lock.writeLock().lock(); System.out.println(Thread.currentThread().getName()+"写入"+key); map.put(key,value); System.out.println(Thread.currentThread().getName()+"已写入"); lock.writeLock().unlock(); } //可以有多个读出 public void get(String key){ lock.readLock().lock(); System.out.println(Thread.currentThread().getName()+"读入"+key); map.get(key); System.out.println(Thread.currentThread().getName()+"已读入"); lock.readLock().unlock(); } }
线程池
程序的运行本质:占用系统的资源!优化资源的使用!=>池化技术
线程池、连接池、内存池、对象池//
程序的运行本质:占用系统的资源!优化资源的使用
池化技术:线程池、连接池、内存池、对象池
线程池三大方法
class Apple{ public static void main(String[] args) { (1)Executors.newSingleThreadExecutor();//单个连接池 (2)ExecutorService threadExecutor =Executors.newFixedThreadPool(5);//创建一个固定的线程池大小 (3)Executors.newCachedThreadPool();//可伸缩 遇强则强 遇弱则弱 for (int i = 0; i <10 ; i++) { threadExecutor.execute(()->{ System.out.println(Thread.currentThread().getName()+"sss"); //线程池结束要关闭线程池 threadExecutor.shutdown(); }); } } }
七大参数
ThreadPoolExecutor
3 个最重要的参数:
-
corePoolSize
: 核心线程数线程数定义了最小可以同时运行的线程数量。 -
maximumPoolSize
: 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。 -
workQueue
: 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。
ThreadPoolExecutor
其他常见参数:
-
keepAliveTime
:当线程池中的线程数量大于corePoolSize
的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了keepAliveTime
才会被回收销毁; -
unit
:keepAliveTime
参数的时间单位。 -
threadFactory
:executor 创建新线程的时候会用到。 -
handler
:饱和策略。关于饱和策略下面单独介绍一下。
拒绝策略
-
ThreadPoolExecutor.AbortPolicy
:抛出RejectedExecutionException
来拒绝新任务的处理。 -
ThreadPoolExecutor.CallerRunsPolicy
:调用执行自己的线程运行任务,也就是直接在调用execute
方法的线程中运行(run
)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。 -
ThreadPoolExecutor.DiscardPolicy
: 不处理新任务,直接丢弃掉。 -
ThreadPoolExecutor.DiscardOldestPolicy
: 此策略将丢弃最早的未处理的任务请求。
class Apple{
public static void main(String[] args) {
//自定义线程池
//2:核心的大小 5:最大线程池的大小 3:超过3秒钟不在等待 TimeUnit.SECONDS单位 new LinkedBlockingDeque<>(3),:后台等待多少个位置
//Executors.defaultThreadFactory() 默认不变
ExecutorService threadPool=new ThreadPoolExecutor(2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());//人满了 不处理这个人物 并抛异常
for (int i = 0; i <10 ; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"sss");
//线程池结束要关闭线程池
threadPool.shutdown();
});
}
}
}