Java多线程笔记总结
来源:互联网 发布:linux 修改文件名 编辑:程序博客网 时间:2024/05/16 18:16
1.线程的三种创建方式
参考之前的总结: 多线程-创建线程的三种方式
对比三种方式:
- 通过继承Thread类实现
- 通过实现Runnable接口
- 实现Callable接口
第1种方式无法继承其他类,第2,3种可以继承其他类;
第2,3种方式多线程可以共享同一个target对象,多个线程处理同一个资源;
一般使用第2,3种方式创建线程。
2.线程的生命周期
1.新建(new) 2.就绪(start) 3.运行(获得cpu资源) 4.阻塞(sleep,IO阻塞等)4.死亡(执行完成,Exception/Error)
3.线程常用方法
join() :Thread对象调用,线程A调用join(),其他线程被阻塞,直到线程A执行完为止。
setDaemon(true) : Thread对象调用,设置成后台线程; 当所有前台线程都死亡,后台线程自动死亡。
- sleep(): 静态方法,让正在执行的线程暂停,进入阻塞状态。
- yield(): 静态方法,让正在进行的线程暂停,进入就绪状态,系统的线程调度器重新调度一次;只有优先级比当前调用yield()的线程高或相同,并且处于就绪状态的线程才能获得执行。
- setPriority(int newPriority), getPriority(): 设置和获取线程的优先级;newPriority范围1-10;Thread三个静态常量,MAX_PRIORITY, 10; NORM_PRIORITY, 5; MIN_PRIORITY, 1;子线程和父线程具有相同的优先级,优先级高的线程比优先级低的线程执行机会更多。
4.线程同步
多个线程访问同一个数据时(线程调度的不确定性),很容易出现线程安全问题。解决办法:引入同步监视器,任意时刻只能有一个线程获得对同步监视器的锁定,当同步代码块执行结束后,该线程释放对该同步监视器的锁定。
“加锁”—>”修改共享资源”->”释放锁”
同步代码块
// obj就是同步监视器synchronized(obj){ 同步代码块}
同步方法
使用synchronized修饰某个方法,则该方法称为同步方法,同步方法的同步监视器是this;
只需对会改变竞争资源的方法进行同步。
任何线程在进入同步代码块或同步方法前,必须获得同步监视器的锁定。
释放同步监视器的锁定的时机:
- 当前线程的同步代码块,同步方法执行结束
- 当前线程在同步代码块,同步方法中遇到break,return终止了执行
- 当前线程在同步代码块,同步方法中出现了未处理的Error或Exception
- 执行了同步监视器对象的wait()方法
同步锁(Lock)
Lock对共享资源的独占访问,每次只能一个线程对Lock对象加锁。
Lock,ReadWriteLock接口,对应的实现类ReentrantLock(可重入锁),ReentrantReadWriteLock。
class A{ private final ReentrantLock lock = ReentrantLock(); public void method(){ // 加锁 lock.lock(); try{ // 修改共享资源 }finally{ // 释放锁 lock.unlock(); } }}
死锁
两个线程互相等待对方释放同步监视器,就发生了死锁。
线程池
在系统启动时,创建大量空闲的线程,将一个Runnable对象或Callable对象传给线程池,线程池会启动一个线程执行对应的run()或call(),当run()或call()执行完成后,该线程返回到线程池成为空闲状态,等待下个Runnable对象或Callable对象。
创建线程池
Executors工厂类,提供如下静态方法创建不同的线程池:
// 具有缓存功能的线程池,系统根据需要创建线程,这些线程会被缓存在线程池中newCachedThreadPool()// 固定数量,可重用的线程池newFixedThreadPool(int nThreads)// 单线程的线程池newSingleThreadExecutor()// 指定线程数量,并可指定延迟时间才执行线程任务newScheduleThreadPool(int corePoolSize)// 单线程,并可指定延迟时间才执行线程任务newSingleThreadScheduleExecutor()
前三个静态方法return ExecutorService
后两个静态方法return ScheduledExecutorService
ExecutorService代表线程池,提供3个方法:
// 将一个Runnable对象提交给线程池,Future返回nullFuture<?> submit(Runnable task)// 将一个Runnable对象提交给线程池,Future返回指定结果resultFuture<T> submit(Runnable task, T result)// 将一个Callable对象提交给线程池,Future返回Callable对象中call()方法Future<T> submit(Callable<T> task)
步骤:
- Executors静态工厂类创建ExecutorService
- 创建Runnable或Callable对象,作为线程执行体
- 调用ExecutorService实例的submit()方法提交Runnable或Callable
- 线程池关闭,调用ExecutorService实例的shutdown()方法
ThreadLocal
线程局部变量,把数据放在ThreadLocal中,就可以为每个线程创建一个该变量的副本,避免并发访问的线程安全问题;
private ThreadLocal<T> threadLocal = new ThreadLocal<>();// 当前线程副本中的值T get();// 删除void remove();// 设置当前线程副本中的值void set(T value);
与同步机制的区别:
同步机制是为了同步多个线程对共享资源的并发访问,是多线程间通信的有限方式;
ThreadLocal隔离多个线程的数据共享,避免多个线程间对共享资源的竞争,不需要对多个线程进行同步。
线程安全集合
通过Collections包装成线程安全集合:
ArrayList, LinkedList, HashSet, TreeSet, HashMap, TreeMap等都是线程不安全;如果多个线程对这些集合读,写时,会破坏这些集合数据的完整性。
Collections提供静态方法将这些集合包装成线程安全的集合。
synchronizedCollection(Collection<T> c)synchronizedList<List<T> list>synchronizedMap(Map<K, V> map)synchronizedSet(Set<T> set)
HashMap m = Collections.synchronizedMap(new HashMap);
线程安全集合:
ConcurrentHashMap, ConcurrentSkipListMap, ConcurrentSkipListSet, ConcurrentLinkedQueue, ConcurrentLinkedDeque
CopyOnWriteArrayList
CopyOnWriteArraySet
- java笔记 多线程总结
- Java多线程笔记总结
- JAVA多线程笔记总结.
- java笔记总结_07_多线程
- JAVA多线程笔记总结(上)
- Java多线程基础知识总结笔记
- JAVA中多线程笔记总结
- 【java多线程编程核心技术】1.java多线程技能-笔记总结
- java中多线程学习笔记总结
- Java多线程总结笔记(一)
- Java多线程编程总结笔记——一多线程基础知识
- Java多线程编程总结笔记——一多线程基础知识
- Java多线程编程总结笔记——02多线程基础知识
- 多线程总结笔记
- 多线程笔记总结
- 黑马程序员之JAVA学习笔记:多线程学习大总结
- java多线程总结笔记1——Runnable和Thread
- java多线程总结笔记2——线程池
- 使用Github
- 在eclipse中查看native代码,能跳转
- 目前书单更新时间2015年12月22日
- 如何在spring中配置定时任务(job)
- Asio驱动开发学习笔记(3)
- Java多线程笔记总结
- JQuery 添加和删除class
- 10个Android开源个性化View控件
- 排序算法复习(2)-- 选择排序
- 设计模式---工厂模式
- 将时间戳转换成当地时间NSDate 转换成当地yyyy-MM-dd HH:mm:ss时间格式
- LeetCode Merge Two Sorted Lists
- xcode构建iOS app时version和build两个版本号区别
- 自动化脚本执行失败原因分析