1.线程安全问题
1.1 相关概念
概述: 多个线程共同操作同一个数据,出现了"数据不准确"的现象,这种现象就被称之为"线程安全问题". 解决: 1.同步代码块 2.同步方法 3.Lock锁 注意: 所谓的"解决线程安全问题",其实就是给线程加锁,简单来说,就是"我操作这个数据的时候,你不能操作,你操作的时候,我不能操作".
1.2 线程加锁
① 同步代码块(掌握)
格式: synchronized(锁对象){ //操作共享数据的代码 } 注意: 1.锁对象可以是任意对象. 2.锁对象必须唯一,推荐使用"当前类名.class" 3.多个线程用的"锁对象"必须是同一个.
② 同步方法(了解)
格式: public synchronized 返回值类型 方法名(参数){} 注意: 1.静态同步方法的锁对象是"类名.class" 2.普通同步方法的锁对象是"this"
③ Lock锁(了解)
语法: private ReentrantLock rl = new ReentrantLock(); //创建"锁对象" rl.lock() //加锁 //操作共享数据的代码 rl.unLock();//释放锁 注意: 1.该操作的锁对象就是"ReentrantLock对象". 2.释放锁的操作必须放在"finally"里边.
2.线程补充
2.1 死锁现象
概述: 多线程中,线程之间彼此占用对方资源,并且不释放,从而导致线程卡死的这种现象,称之为"死锁" 解决: 尽量避免锁的交叉嵌套.
2.2 生产者消费者模式(了解)
概述: "生产者消费者模式"的核心是"多线程之间彼此叫醒对方去工作的思想",也就是"线程间通讯" 方法: 锁对象.wait(); //当前线程等待(线程在锁上等待) 锁对象.notify(); //随机唤醒锁上等待的一个线程 锁对象.notifyAll();//唤醒锁上所有等待的线程
2.3.线程的状态(了解)
NEW:新建 RUNNABLE:可运行状态 BLOCKED:阻塞状态 WAITING:无限等待状态 TIMED_WAITING:计时等待 TERMINATED:终止
3.线程池(熟悉)
3.1 系统线程池
概述: 线程池,就是存储线程的池子.线程池可以创建和回收线程. 创建: ExecutorService es = Executors.newCachedThreadPool(); //创建一个默认线程池.内部最多有int最大值个线程 ExecutorService es = Executors.newFixedThreadPool(int num); //创建一个线程池.内部线程最大数量为num 使用: public Future submit(Runnable task); //提交任务.把要执行的任务交给线程池,由线程池分配线程执行 public void shutdown(); //关闭线程池
3.2 自定义线程池
概述: ThreadPoolExecutor可以用来自定义线程池. 构造: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler){...} 参数: corePoolSize: //核心线程数,不能小于0 maximumPoolSize://最大线程数,不能小于等于0,且必须大于等于核心线程数 keepAliveTime: //空闲线程最大存活时间值(值),不能小于0 unit: //空闲线程最大存活时间单位,一般使用TimeUtil中的选项 workQueue: //任务队列(阻塞队列),该参数用于确定排队的数量,不能为null. 语法:new ArrayBlockingQueue<>(数量); threadFactory: //创建线程的方式,一般为"Executors.defaultThreadFactory()"默认方式,不能为null handler: //任务的拒绝策略(多余任务的处理方式) 拒绝策略: new ThreadPoolExecutor.AbortPolicy(); //丢弃任务并抛出RejectedExecutionException异常。是默认的策略。 new ThreadPoolExecutor.DiscardPolicy(); //丢弃任务,但是不抛出异常 这是不推荐的做法。 new ThreadPoolExecutor.DiscardOldestPolicy(); //抛弃队列中等待最久的任务 然后把当前任务加入队列中。 new ThreadPoolExecutor.CallerRunsPolicy(); //调用任务的run()方法绕过线程池直接执行。