怎么建网站不用买空间,学校网站建设经验介绍,网站的内容有哪些内容,中山网站建设文化咨询一、Android线程基础
1.线程和进程
一个进程最少一个线程#xff0c;进程可以包含多个线程进程在执行过程中拥有独立的内存空间#xff0c;而线程运行在进程内
2.线程的创建方式
new Thread#xff1a; 缺点#xff1a;缺乏统一管理#xff0c;可能无限制创建线程进程可以包含多个线程进程在执行过程中拥有独立的内存空间而线程运行在进程内
2.线程的创建方式
new Thread 缺点缺乏统一管理可能无限制创建线程相互之间竞争可能占用过多的系统资源导致死机或OOM new Thread(new Runnable() {Overridepublic void run() {}}).start();class MyThread extends Thread{Overridepublic void run() {super.run();}}new MyThread().start();
AysncTask轻量级异步任务工具类提供任务执行的进度回调给UI线程 使用场景需要知道任务执行的进度多个任务串行执行 缺点生命周期和宿主的生命周期不同步可能发生内存泄漏默认情况下任务串行执行 作为用来替代Thread Handler的辅助类AsyncTask可以很轻松地执行异步任务并更新ui但由于context泄露回调遗漏configuration变化导致崩溃平台差异性等原因在api 30Android 11)中AsyncTask被正式废弃 使用execute方法串行执行即先来后到如果其中有一条任务休眠或者执行时间过长后面的任务都将被阻塞 使用内置THREAD_POOL_EXECUTOR线程池并发执行
HandlerThread适用于主线程需要和工作线程通信或者持续性任务比如轮询所有任务串行执行 缺点不会像普通线程一样主动销毁资源会一直运行可能造成内存泄漏可以定义成静态防止内存泄漏
IntentService适用于任务需要跨界面读取任务执行的进、结果。比如后台上传图片、批量操作数据库等。任务完成后会自我结束不需要手动stopServiceThreadPoolExecutor适用快读出来大量耗时较短的任务场景 Executors.newCacheThreadPool();//线程可复用线程池Executors.newFixedThreadPool();//固定线程数量线程池Executors.newScheduleThreadPool();//可指定定时任务线程池Executors.newSingleExecutor();//线程数量为1的线程池
3.线程的优先级
线程的优先级具有继承性设置优先级的方法 java apijava.lang.Thread.setPriority(int newPriority);优先级必须为[1~10]优先级的值越高获取CPU时间片的概率越高UI线程的优先级为5 效果不是很明显Android apiandroid.os.Process.setThreadPriority(int newPriority);优先级可设置[-20~19]优先级的值越低获取时间片的概率越高UI线程的优先级为-10 效果明显
4.线程的状态
NEW初始状态线程被新建还没有调用start方法RUNNABLE运行状态包括运行中和就绪BLOCKED阻塞状态表示线程阻塞于锁WAITING等待状态需要其他线程通知唤醒TIME_WAITING超时等待状态表示可以在指定的时间超过后自行返回TERMINATED终止状态表示当前线程已经执行完毕
关键方法
wait等待线程池释放资源对象锁可使用notifynotifyAll或等待超时时间来唤醒join等待目标线程执行完后再执行此线程yield暂停当前正在执行的线程对象不会释放当前线程持有的任何锁资源使用优先级或更高优先级的线程有执行的机会这个方法机会用不到sleep使调用线程进入休眠状态一般情况下会释放线程锁对象但如果在一个synchronized块中执行sleep线程虽会休眠但不会释放资源对象锁
5.线程间消息通讯
主线程向子线程发送消息
二、多线程开发核心知识点
1.线程并发安全
本质能够让并发线程有序的运行可能是先来后到排队也可能被插队同一时刻只能一个线程有权访问同步资源线程执行的结果能够对其它线程可见
2.线程安全的分类
根据线程要不要锁住同步资源 锁住悲观锁 synchronized ReentrantLock不锁住乐观锁 AtomicInteger AtomicBoolean锁住同步资源失败要不要阻塞 阻塞阻塞锁 synchronized ReentrantLock不阻塞自旋锁 AtomicInteger AtomicBoolean 获取资源锁时要不要插队 插队公平锁 ReentrantLock不插队非公平锁 synchronized ReentrantLock一个线程中的多个流程能不能获取同一把锁 可重入锁 synchronized ReentrantLock不可重入锁多线程共享一把锁 能共享锁 RendLock不能排他锁 WriteLock多线程竞争同步资源 synchronized 不锁住资源多个线程中只有一个能修改成功其他会重试 无锁同一线程执行同步资源时自动获取锁 偏向锁多个线程竞争资源时没有获取到资源的线程自选等待 轻量级锁多个线程竞争资源时没有获取到资源的线程被阻塞等待唤醒 重量级锁
3.如何线程安全
AtomicInterger 原子包装类
CAS实现无锁数据更新自旋的设计能够有效避免线程因阻塞-唤醒带来的系统资源开销适用场景多线程计数原子操作并发数量小使用案例 AtomicInteger atomicInteger new AtomicInteger(1);atomicInteger.getAndIncrement();atomicInteger.getAndAdd(2);atomicInteger.getAndDecrement();atomicInteger.getAndAdd(-2);
volatile 可见性修饰
volatile修饰的成员变量在每次被线程访问时都强迫从共享内存重新读取该成员的值而且当成员变量值发生变化时强迫将变化的值重新写入共享内存缺点不能保证原子性不能解决非原子操作的线程安全性性能不及原子类高使用案例 volatile int count 0;public void test() {// 赋值操作是原子性操作对其他线程可见count 1;//非原子操作其他线程不可见count count 1;count;}
synchronized
锁方法。加在方法上未获取到对象锁的其他线程都不可以访问该对象锁Class对象。加在static方法上相当于给Class对象加锁哪怕是不同的Java对象实例也需要排队执行锁代码块。未获取到对象锁的其他线程可以执行同步代码块之外的代码
优势哪怕一个同步方法中出现了异常那么JVM也能够为我们自动释放锁能主动从而规避死锁不需要开发者主动释放锁
劣势
必须要等到获取锁对象的线程执行完成或出现异常才能释放掉不能中途释放锁不能中断一个正在试图获取锁的线程多线程竞争的时候不知道获取锁成功与否不够灵活每个锁仅有单一的条件不能设定超时
ReentrantLock
悲观锁可重入锁公平锁非公平锁
基础用法 ReentrantLock lock new ReentrantLock();try {lock.lock();//……} finally {lock.unlock();}//获取锁获取不到会阻塞lock.lock();//尝试获取锁成功返回truelock.tryLock();//在一定的时间内去不断尝试获取锁lock.tryLock(3000, TimeUnit.MICROSECONDS);//可使用Thread.interrupt()打断阻塞退出竞争让给其他线程lock.lockInterruptibly();
可重入避免死锁 ReentrantLock lock new ReentrantLock();public void doWork() {try {lock.lock();doWork();//递归调用使得统一线程多次获得锁} finally {lock.unlock();}}
公平锁所有进入阻塞的线程排队依次均有机会执行
使用场景交易
//传入true 就是公平锁传入false 或者不传就是非公平锁
ReentrantLock lock new ReentrantLock(true);
非公平锁默认允许线程插队避免每一个线程都进入阻塞在唤醒带来的性能开销。性能高因为线程可以插队但是会导致队列中可能存在线程饿死的情况一直得不到锁一直得不到执行
使用场景synchronized很多场景都是非公平锁
进阶用法 -- Condition条件对象 Condition worker lock.newCondition();//进入阻塞等待唤醒worker.await();//唤醒指定线程worker1.signal();
共享锁排他锁
共享锁所有线程都可以同时获得并发量高。如读操作排他锁同一时刻只能一个线程有权修改资源。如写操作
ReentrantReadWriteLock.ReadLock
ReentrantReadWriteLock.WriteLock
三、正确使用锁和原子类
1.减少持锁时间
尽管锁在同一时间只能允许一个线程持有其他想要占用锁的线程都得在临界区外等待锁的释放这个等待的时间要尽可能的短
2.锁分离
读写锁分离写锁才需要同步处理。对于大多数应用来说读的场景更多一些读写锁分离可以提高系统性能
3.锁粗化
多次加锁释放锁合并成一次
对于一些不需要同步的代码但能很快执行完毕前后都有锁这种情况可以进行锁粗化整合成一次锁请求释放。锁请求、释放是需要性能开销的
四、线程池
1.优势
减低资源消耗。通过重复利用已创建的线程减低线程创建和销毁造成的消耗提高响应速度。当任务到达时任务可以不需要等待线程创建就能立即执行提高线程的可管理性。线程是稀有资源如果无限制的创建不仅会消耗系统资源还会降低系统的稳定性使用线程池可以进行统一的分配调优和监控。
2.Java中默认的线程池
线程池的默认构建 ThreadPoolExecutor executor new ThreadPoolExecutor(5, 20, 5, TimeUnit.SECONDS,new PriorityBlockingQueue());executor.execute(() - {});// 源码public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueRunnable workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {}
参数
corePoolSize线程池中的核心线程数量maximumPoolSize最大能创建的线程数量keepAliveTime非核心线程最大的存活时间unitkeepAliveTime的时间单位workQueue等待队列当任务提交时如果线程中线程数量大于等于corePoolSize的时候把任务放入等待队列threadFactory线程创建工厂默认使用Executors.defaultThreadFactory()来创建线程线程具有相同的NORM_PRIORITY优先级并且是非守护线程handler线程池的饱和就决策略。如果阻塞队列满了并且没有空闲的线程这时如果继续提交任务就需要采取一种策略处理该任务
JUC包下提供的集中线程池 // 单一线程数同时只有一个线程存活但是线程等待队列无界Executors.newSingleThreadExecutor();// 线程可复用线程池核心线程数为0最大可创建的线程数为Interger.max线程复用存活时间为60sExecutors.newCachedThreadPool();// 固定线程数量的线程池Executors.newFixedThreadPool(5);// 可执行定时任务延迟任务的线程池Executors.newScheduledThreadPool(5);
线程池的重要方法
//提交任务交给线程池调度
void execute(Runnable command) //关闭线程池等待执行任务完成不接受新的任务但可以继续执行池子中已添加到等待队列的任务
void shutdown()//关闭线程池不等待执行任务完成不接受新的任务也不再处理等待队列中的任务打断正在执行的任务
void shutdownNow()//返回线程池中所有任务的数据
long getTaskCount()//返回线程池中已执行完毕的任务数量
long getCompletedTaskCount() //返回线程池中已创建的线程数量
int getPoolSize()//返回当前正在运行的线程数量
int getActiveCount()
execute提交任务流程 addWorker的工作任务
检查线程池状态,能否继续创建线程把runnable封装成worker,添加到工作队列启动新建的线程runWorker方法中开启whille循环执行本次任务本次任务结束后去检查等待队列中是否有任务拿来继续执行达到复用目的
retry双层for循环流程控制使用retry可以退出外层循环 int count 0;retry:for (int i 0; i 10; i) {for (int j 0; j 10; j) {count;if (count 3) {break;}if (count 4){break retry;}}}
五、协程