缺点:缺乏统一管理,可能无限制创建线程,相互之间竞争,可能占用过多的系统资源导致死机或OOM
- new Thread(new Runnable() {
- @Override
- public void run() {
-
- }
- }).start();
-
- class MyThread extends Thread{
- @Override
- public void run() {
- super.run();
- }
- }
- new MyThread().start();
使用场景:需要知道任务执行的进度,多个任务串行执行
缺点:生命周期和宿主的生命周期不同步,可能发生内存泄漏,默认情况下任务串行执行
作为用来替代Thread + Handler的辅助类,AsyncTask可以很轻松地执行异步任务并更新ui,但由于context泄露,回调遗漏,configuration变化导致崩溃,平台差异性等原因,在api 30(Android 11)中AsyncTask被正式废弃:
使用execute方法,串行执行,即先来后到,如果其中有一条任务休眠,或者执行时间过长,后面的任务都将被阻塞
使用内置THREAD_POOL_EXECUTOR线程池,并发执行
缺点:不会像普通线程一样主动销毁资源,会一直运行,可能造成内存泄漏(可以定义成静态,防止内存泄漏)
关键方法:
主线程向子线程发送消息
本质:能够让并发线程有序的运行(可能是先来后到排队,也可能被插队,同一时刻只能一个线程有权访问同步资源),线程执行的结果,能够对其它线程可见
- AtomicInteger atomicInteger = new AtomicInteger(1);
-
- atomicInteger.getAndIncrement();
- atomicInteger.getAndAdd(2);
-
- atomicInteger.getAndDecrement();
- atomicInteger.getAndAdd(-2);
- volatile int count = 0;
-
- public void test() {
- // 赋值操作是原子性操作,对其他线程可见
- count = 1;
-
- //非原子操作,其他线程不可见
- count = count + 1;
- count++;
- }
优势:哪怕一个同步方法中出现了异常,那么JVM也能够为我们自动释放锁,能主动从而规避死锁,不需要开发者主动释放锁
劣势:
悲观锁,可重入锁,公平锁,非公平锁
- ReentrantLock lock = new ReentrantLock();
- try {
- lock.lock();
- //……
- } finally {
- lock.unlock();
- }
-
-
- //获取锁,获取不到会阻塞
- lock.lock();
- //尝试获取锁,成功返回true
- lock.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 worker = lock.newCondition();
-
- //进入阻塞,等待唤醒
- worker.await();
-
- //唤醒指定线程
- worker1.signal();
共享锁,排他锁
- ReentrantReadWriteLock.ReadLock
- ReentrantReadWriteLock.WriteLock
尽管锁在同一时间只能允许一个线程持有,其他想要占用锁的线程都得在临界区外等待锁的释放,这个等待的时间要尽可能的短
读写锁分离,写锁才需要同步处理。对于大多数应用来说,读的场景更多一些,读写锁分离,可以提高系统性能
多次加锁,释放锁合并成一次
对于一些不需要同步的代码,但能很快执行完毕,前后都有锁,这种情况可以进行锁粗化,整合成一次锁请求,释放。(锁请求、释放是需要性能开销的)
- ThreadPoolExecutor executor = new ThreadPoolExecutor(
- 5, 20, 5, TimeUnit.SECONDS,new PriorityBlockingQueue<>());
- executor.execute(() -> {
-
- });
-
- // 源码
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue
workQueue, - ThreadFactory threadFactory,
- RejectedExecutionHandler handler) {
- }
- // 单一线程数,同时只有一个线程存活,但是线程等待队列无界
- Executors.newSingleThreadExecutor();
- // 线程可复用线程池,核心线程数为0,最大可创建的线程数为Interger.max,线程复用存活时间为60s
- Executors.newCachedThreadPool();
- // 固定线程数量的线程池
- Executors.newFixedThreadPool(5);
- // 可执行定时任务,延迟任务的线程池
- Executors.newScheduledThreadPool(5);
- //提交任务,交给线程池调度
- void execute(Runnable command)
-
- //关闭线程池,等待执行任务完成,不接受新的任务,但可以继续执行池子中已添加到等待队列的任务
- void shutdown()
-
- //关闭线程池,不等待执行任务完成,不接受新的任务,也不再处理等待队列中的任务打断正在执行的任务
- void shutdownNow()
-
- //返回线程池中所有任务的数据
- long getTaskCount()
-
- //返回线程池中已执行完毕的任务数量
- long getCompletedTaskCount()
-
- //返回线程池中已创建的线程数量
- int getPoolSize()
-
- //返回当前正在运行的线程数量
- int getActiveCount()

addWorker的工作任务
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;
- }
- }
- }