【JUC(三)】中断与等待唤醒

JUC 串讲 JUC 知识串讲 阅读详情

1. interrupt() 相关方法

interrupt(),interrupted() 和 isinterrupted() 的区别

public void interrupt():

将线程的中断标记设置为 true,并不是真的停止该线程。
如果线程处于  wait()、join()、sleep() 方法的阻塞当中。中断标记会被清除。也就是通过isInterrupted,interrupted 方法返回均为 false。同时抛出一个InterruptedException异常。

public boolean isInterrupted()
判断某个具体线程对象是否被中断,返回的是线程的中断标记(true or false)

public static boolean interrupted()
返回当前线程的中断状态,然后将当前线程的中断状态设为false。
如果线程中断标记为true,只有第一次调用时会返回 true。之后调用都是false。(这个方法会清除线程的中断状态)
  • 三者的使用
public static void interruptMethod03() throws InterruptedException {
    Thread t1 = new Thread(()->{
        // 当要 interrupt 一个正常运行线程时,
        // 线程的打断标记会被赋值为 true ,但是线程不会立刻中断。
        Thread now = Thread.currentThread();
        int i = 0;
        boolean flag = false;
        while(true){
            flag = Thread.interrupted();
            System.out.println(++i);
            if(flag){
                // 可以说明:Thread.interrupted() 是清除打断标记
                System.out.println("t1.interrupt()执行后,第一次调用 Thread.interrupted(). 应该返回true");
                System.out.println("flag: "+ flag);
                System.out.println("t1.interrupt()执行后,第二次调用 Thread.interrupted(). 应该返回false");
                System.out.println("Thread.interrupted(): "+Thread.interrupted());

                System.out.println();

                System.out.println("再一次调用 t1.interrupt() 之后");
                now.interrupt();
                System.out.println("now.isInterrupted()【不会将打断状态设置为false】. 应该返回true");
                System.out.println("now.isInterrupted(): "+now.isInterrupted());

                System.out.println("Thread.interrupted()【将打断状态设置为false】.当前应该返回true");
                System.out.println("Thread.interrupted(): "+Thread.interrupted());
                System.out.println("经过Thread.interrupted()对打断状态的清除,now.isInterrupted()应该返回false,now.isInterrupted(): "
                                   +now.isInterrupted());
                // 当前线程已经被打断(也即其他线程调用了当前线程的interrupt方法)
                System.out.println(now.getName() + " 线程被打断.....");
                break;
            }
        }
    },"t1");
    t1.start();
    Thread.sleep(100);
    t1.interrupt();
}

通过上面的例子可以了解到:

在Java中没有办法立即停止一条线程(处于阻塞状态除外),然而停止线程却显得尤为重要,如取消一个耗时操作。

因此,Java提供了一种用于停止线程的协商机制——中断。

中断只是一种协作协商机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。

比如线程A调用了线程B的 public void interrupt():方法。线程B只能在 run 方法中使用 isInterrupted 与 interrupted 方法的返回值确定是否中断,然后自行编写中断逻辑。

  • 阻塞线程被中断的情况
public static void main(String[] args) {
    Thread t1 =  new Thread(()->{
        while(true){
            if(Thread.currentThread().isInterrupted()){
                System.out.println(Thread.currentThread().getName()+"\t"+
                                   "中断标志位:"+Thread.currentThread().isInterrupted()+"程序终止");
                break;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
                // 加了这个,程序可以终止,只会爆异常
                // 如若不在异常处理部分加入 interrupt,程序会一直报异常。
                // 因为 处于阻塞的线程被 interrupt 后,会将线程中断标记设置为false。
                // 这样就导致 Thread.currentThread().isInterrupted() 返回false,程序无法中断
                Thread.currentThread().interrupt();
            }
            System.out.println("-----hello InterruptDemo03");
        }
    },"t1");
    t1.start();
    try {
        TimeUnit.MILLISECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
    new Thread(() -> t1.interrupt()).start();
}

2. LockSupport

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语,其中park()和unpack()而作用分别是阻塞线程和解除阻塞线程。

3. 线程的等待唤醒机制

  • 方式一:使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程
  • 方式二:使用JUC包中的Condition的await()方法让线程等待,使用signal()方法唤醒线程
  • 方式三:LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程

3.1 Object中wait和notify

  • wait与notify需要成对出现,且需要在同步代码块或同步方法中使用。
  • 要先 wait,后 notify。
public static void main(String[] args) {
    Object objectLock = new Object();

    new Thread(()->{
        synchronized(objectLock){
            System.out.println(Thread.currentThread().getName()+" come in 。。。");
            try {
                objectLock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" 被唤醒。。。");
        }
    },"Thread 01").start();

    new Thread(()->{
        synchronized(objectLock){
            System.out.println(Thread.currentThread().getName()+" come in 。。。");
            try {
                objectLock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" 被唤醒。。。");
        }
    },"Thread 03").start();

    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    new Thread(()->{
        synchronized(objectLock){
            //  如果只有两个线程,一个等待,一个唤醒。就调用notify
            // objectLock.notify();
            // 如果有多个线程等待,就需要调用 notifyAll。 一次唤醒全部等待线程
            objectLock.notifyAll();
            System.out.println(Thread.currentThread().getName()+" 唤醒通知已经发送。。。");
        }
    },"Thread 02").start();
}

3.2 Condition中await和signal

  • Condition中的线程等待和唤醒方法,需要先获取锁
  • 一定要先await后signal,不要反了
  • Condition可以拥有多个,这样面对不同的场景,可以创建不同的 condition。解决 Object对象中多个wait只能notifyAll的情况。
// 方式二:使用`JUC`包中的`Condition`的`await()`方法让线程等待,使用`signal()`方法唤醒线程
public static void awaitAndSignal(){
    Lock lock = new ReentrantLock();
    // 可以针对不同的业务拥有不同的 condition,等待唤醒可以达到具体某个线程的粒度。
    Condition condition = lock.newCondition();
    Condition conditionThread03 = lock.newCondition();

    new Thread(()->{
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "\t -----------come in");
            condition.await();
            System.out.println(Thread.currentThread().getName() + "\t -----------被唤醒");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    },"Thread 01").start();

    new Thread(()->{
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "\t -----------come in");
            conditionThread03.await();
            System.out.println(Thread.currentThread().getName() + "\t -----------被唤醒");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    },"Thread 03").start();

    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    new Thread(()->{
        lock.lock();
        try {
            condition.signal();
            conditionThread03.signal();
            System.out.println(Thread.currentThread().getName() + "\t -----------发出通知");
        } finally {
            lock.unlock();
        }
    },"Thread 02").start();
}

3.3 Object和Condition使用的限制条件

  • wait 与 notify 必须在 synchronized 快中使用,否则会报异常。
  • await 与 signal 需要配合 lock 使用。
  • 二者的等待与唤醒的顺序是不能错的。

3.4 LockSupport类中的park等待和unpark唤醒

  • LockSupport 使用了一种名为Permit(许可)的概念来做到阻塞和唤醒线程的功能
  • 每个线程都有一个许可(permit),且累加上限为1(也就是说,要么有一个许可,要么没有许可)。
  • 当程序调用 LockSupport.park();时,如果当前线程没有许可,就进行阻塞,有许可就放行。
  • LockSupport.unpark(t1); 给 t1 线程一个许可(permit),

例子:

// 方式三:`LockSupport`类可以`阻塞当前线程`以及`唤醒指定被阻塞的线程`
// LockSupport 使用了一种名为Permit(许可)的概念来做到阻塞和唤醒线程的功能.每个线程都有一个许可(Permit),许可证只能有一个,累加上限是1。
public static void parkAndUnpark(){
    /**
      * t1	 -----------come in
       * t2	 ----------发出通知
       * t1	 ----------被唤醒
       */
    Thread t1 = new Thread(() -> {
        System.out.println(Thread.currentThread().getName() + "\t -----------come in");
        LockSupport.park();
        System.out.println(Thread.currentThread().getName() + "\t ----------被唤醒");
    }, "t1");
    t1.start();

    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    new Thread(() -> {
        LockSupport.unpark(t1);
        System.out.println(Thread.currentThread().getName() + "\t ----------发出通知");
    }, "t2").start();
}

例子:先调用 unpark , 在调用 park。不会报异常,也不会阻塞。

/*
    先调用 unpark 后调用 park
     */
public static void parkAndUnpark02(){
    	/**
         * t1	 -----------come in
         * t2	 ----------发出通知
         * t1	 ----------被唤醒
         */
    Thread t1 = new Thread(() -> {
        System.out.println(Thread.currentThread().getName() + "\t -----------come in");
        System.out.println(Thread.currentThread().getName() + "\t ----------unpark");
        LockSupport.unpark(Thread.currentThread());

        System.out.println(Thread.currentThread().getName() + "\t ----------park");
        // 上面已经 unpark ,得到了一个 permit。 
        // 所以调用一次 park 不会产生阻塞。
        // 但是如果调用2两次及以上,就会产生阻塞。应该 permit 不累加,最大为1。
        LockSupport.park();
        System.out.println(Thread.currentThread().getName() + "不会阻塞");
    }, "t1");
    t1.start();
}
  • 其他方法
权限方法签名与解释
static ObjectgetBlocker(Thread t)Returns the blocker object supplied to the most recent invocation of a park method that has not yet unblocked, or null if not blocked.
static voidpark()Disables the current thread for thread scheduling purposes unless the permit is available.
static voidpark(Object blocker)Disables the current thread for thread scheduling purposes unless the permit is available.
static voidparkNanos(long nanos)Disables the current thread for thread scheduling purposes, for up to the specified waiting time, unless the permit is available.
static voidparkNanos(Object blocker, long nanos)Disables the current thread for thread scheduling purposes, for up to the specified waiting time, unless the permit is available.
static voidparkUntil(long deadline)Disables the current thread for thread scheduling purposes, until the specified deadline, unless the permit is available.
static voidparkUntil(Object blocker, long deadline)Disables the current thread for thread scheduling purposes, until the specified deadline, unless the permit is available.
static voidunpark(Thread thread)Makes available the permit for the given thread, if it was not already available.
【ARM Coresight | AMBA BUS | Cache 与 MMU/MPU | CoreLink | GCC | CSH 专栏导读】 1. ARM Coresight(SoC-400/SoC-600) 专栏 2. ARMv8/v9 CPU/Cache 专栏 3. Linux ARM AMBA 总线 专栏 4. Trace32/DS-5 专栏。。。 阅读详情

相关推荐

阿里云大模型ACP认证模拟考试(三)

【摘要】:在阿里云大模型高级工程师 ACP 认证暂无真题题库的现状下,模拟题具有重要意义。其依照真实考试设计,涵盖题型、题量与分值分布,助力考生熟悉考试框架,合理分配答题时间精力,提升效率。同时,模拟题紧扣官方课程,能帮助考生精准定位知识盲点,如大模型架构原理和通义千问应用实践等重点内容,以便针对性完善知识体系。此外,通过练习模拟题,考生可掌握不同题型的解题思维与技巧,快速洞察复杂题目本质,提高答题准确率。

davidkorhenn的博客 3578

关于对 JUC 的 Interrupt 和 Interrupted 方法的一些理解

在讲到中断方法之前,我们先谈谈什么是线程中断。在Java并发编程中,线程中断是一种协作机制,允许一个线程向另一个线程发出停止正在进行的操作的请求通知。这种通知是通过设置所谓的“中断状态”来实现的。但重要的是,线程中断不是强迫线程停止,而是给线程一个机会来优雅地结束它的执行。这个“机会”实际上是在告诉线程:“你可以继续进行,但有一个请求建议你在下一个合适的时刻停下来。”线程可以检查这个请求(即中断状态),然后决定是否以及何时响应。

weixin_59736343的博客 2204

Endnote 导入参考文献的时候,格式错误太多了。et.al错误,国标GBT7714在endnote中的详细配置教程,适用于本科,硕士论文文献插入的模板

EndNote插入文献常遇到以下错误主要如下: 等、et al不分; 英文作者全名大写; 期刊名字使用了缩写(图片里没有体现;卷号、期号缺失时出现乱码,多了半个括号;页码范围略去了相同部分;没有悬挂缩进,本文全部解决,全网最细

sakura的博客 3万+

多线程JUC 第2季 中断线程(Interrupted,Interrput,IsInterput)

1.public void interrupt(): 实例方法,仅仅是设置线程中断状态为true,发起一个协商而不会立刻停止线程。静态方法,判断当前线程是否中断并清除当前线程的中断状态。做两件事:a)返回当前线程的中断状态,测试当前线程是否已经中断。b)将当前线程的中断状态清零并重新设置为true,清除线程的中断状态。3.public boolean isinterrupted():实例方法判断当前线程是不是中断,检测中断标志位。

健康平安的活着的专栏 842

【基金量化研究系列】基金绩效归因模型——Brinson多期归因模型之python实现

文章目录1. 引言2. Brinson多期归因模型的Python实现2.1 基准数据读取模块2.2 持仓数据读取模块2.3 持仓收益与基准计算模块2.4 Brinson多期归因模型核心算法Brinson_Multiple2.5 主函数模块3. 归因结果写在最后 1. 引言 在上文中,我们已经介绍了Brinson归因模型的基本思想。那么,就让我们动起手来,实现这一方法吧! 在Brinson多期归因模型实现的过程中,本文使用模块化方法,将整个实现过程划分为如下五个功能板块: Module 1: 基准数据读取模

Mikey_Sun的博客 2万+

对称加密和非对称加密,数字签名和证书

在对称加密中,任何人都可以使用公钥进行加密。在数字签名中,任何人都可以使用公钥验证签名。数字签名,其实就是将非对称加密反过来使用。公钥私钥非对称加密发送者加密时使用接收者解密时使用数字签名验证者验证签名时使用签名者生成签名时使用谁持有密钥?只要有需要,任何人都可以持有个人持有既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密。公钥负责加密,私钥负责解密。既然是签名,那肯定是不希望有人冒充我发消息,所以只有我才能签名。私钥负责签名,公钥负责验签。

m0_70432049的博客 1409

JUC学习:interrupt线程中断机制

主要介绍了interrupt()、interrupted()、isInterrupted()方法的概念与使用方法。

qq_45266399的博客 302

全志DRM框架下LVDS双屏异显配置实战

本文详细介绍了在全志DRM框架下配置LVDS双屏异显的实战经验。涵盖硬件连接、内核配置、设备树修改、背光控制及U-Boot适配等关键步骤,重点解析屏参转换技巧与双屏route配置,帮助开发者解决工业控制台等多屏应用中的显示适配问题,提升开发效率。

rnn9storyteller的博客 813

Juc22_什么是中断、interrupt、isInterrupted、interrupted方法源码解析、如何使用中断标识停止线程

文章目录①. 什么是中断②. 源码解读(中断的相关API)③. 如何使用中断标识停止线程 ①. 什么是中断 ①. 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,所以,Thread.stop、Thread.suspend、Thread. resume都已经被废弃了 ②. 在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的机制 — 中断 ③. 中断只是一种协作机制,Java没有给中断增加任何语法,中断的

所得皆惊喜 2829

Pipeline更多理解

Pipe 类型用途VIGVideo Image Generator:用于图层显示,支持 scaling、rotationRGB简单图层显示,较低优先级DMA主要用于 writeback / WFD / composition output,即从 framebuffer 输出到外部设备(或 memory)Cursor小图层,用于显示指针等很可能是:分别用于主屏、仪表、虚拟显示的输出路径或者用于不同的 display 去做 GPU_TARGET / writeback 的拷贝你看到的意思。

Damon_X的博客 1052

JavaScript教程-字符集,Unicode转义序列,标识符,数据类型,数字,未定义值,浮点数,字符串,引用数据类型,类型检测,类型转换,运算符,关系运算符,

前端学习

VAN 212

juc之基本概念详解分析

基本概念 中断 boolean interrupted() 返回当前调用线程,不是调用该方法的实例对象是否中断,若是中断,清除中断标志位 boolean isinterrupted() 返回调用线程是否中断**,若是中断,恢复中断标志位** void interupt() 将调用线程中断标志为true public static boolean interrupted() { ...

幻想波普星 693

财务数字化——解读美的战略规划之财务组织体系建设【附全文阅读】

本文提出适用于集团企业的财务管控方案,面向财务负责人、HR及战略规划人员。方案整合四种管控模式,结合500强案例,构建"职能定位-架构设计-权责划分-人才发展"体系,涵盖财务五大模块。通过明确总部与事业部权责边界,提供组织架构等实操框架,旨在平衡财务管控与业务支持,提升效率与风控能力,满足集团财务体系规范化建设需求。

cdfunlove的博客 663

JUC并发编程03——线程中断与LockSupport等待唤醒

JUC并发编程03——LockSupport与线程中断

qq_62767608的博客 1235

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

JUC - 线程中断与线程等待、唤醒(LockSupport)

什么是中断机制?​ 首先 ​ 一个线程不应该由其他线程来强制中断或停止,而是应该有线程自己自行停止,自己来决定自己的命运。 ​ 所以,Thread.stop, Thead.suspend, Thead.resumer都已经被废弃了。​ 其次 ​ 在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。 ​ 因此,Java提供了一种用于停止线程的协商机制–中断,即中断标识协商机制。中断只是一种协商协作机制,Java中没有给中断增加任何语法,中断的过程完全需要程序员自己实现。

Lifelong learning 4591

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

JUC并发编程第五篇,如何优雅的使用线程中断机制和线程等待唤醒机制?

一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。Java提供了一种用于停止线程的机制——中断。中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。若要中断一个线程,你需要手动调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设成true,接着你需要自己写代码不断地检测当前线程的标识位,如果为true,表示别的线程要求这条线程中断,此时究竟该做什么需要你自己写代码实现。

I wanna be myself, where I Belong. 788

【尚硅谷周阳--JUC并发编程】【第五章--LockSupport与线程中断】

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语;LockSupport是一个线程阻塞工具,所有的方法都是静态方法,可以让线程在任意位置阻塞,阻塞之后也有对应的唤醒方法。归根结底,LockSupport调用的unsafe中的native代码;LockSupport提供park()和unpark()方法实现阻塞线程和解除线程阻塞的过程,LockSupport和每个使用它的线程都有一个许可(permit)关联。每个线程都有一个相关的permit,permit最多只有一个

qq_45046083的博客 1010

JUC多线程:线程通信之虚假唤醒和定制化通信

在多线程编程中,线程间通信是开发者必须掌握的硬核技能。生产者-消费者问题作为最经典的线程通信案例,完美展现了资源竞争与协调的核心矛盾。本文将带你从虚假唤醒的致命陷阱出发,通过传统synchronized方案与JUC高阶方案的对比,深入剖析多线程通信的本质,手把手教你写出健壮的线程协调代码!掌握多线程通信就像获得协调交响乐团的指挥棒,只有深刻理解每个线程的行为特征,才能编写出高效稳定的并发程序。希望本文能帮助你在多线程世界中游刃有余!7、传统的生产者消费者问题、防止虚假唤醒_哔哩哔哩_bilibili。

2201_75525624的博客 1353

JUC探险-9、Condition

JUC探险-9、Condition

NarutoConanKing的博客 429

线程中断,等待,唤醒与ThreadLocal

线程中断,等待,唤醒与ThreadLocal

weixin_45820447的博客 383

java JUC并发编程 第三章 中断机制

LockSupport,volatile,AtomicBoolean,java,多线程

记录工作历程 246

JUC高级三:LockSupport与线程中断

首先 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。 所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。 其次 在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的机制——中断。 中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。

qq_31745863的博客 2200

JUC并发编程(中)

volatile 写之前的操作,都禁止重排序到volatile之后volatile读之后的操作,都禁止重排序到volatile 之前volatile 写之后volatile读,禁止重排序。

sinat_35187083的博客 1030

JUC-LockSupport与线程中断

LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,当然阻塞之后肯定得有唤醒的方法.

一生烟雨的博客 684

多线程(十二)JUC之Condition等待与唤醒

Condition条件唤醒 在并行程序中, 避免不了某些线程要预先规定好的顺序执行, 例如, 先新增再修改, 先买后卖, 先进后厨 … 对于这类场景, 使用JUC的Condition对象非常合适 JUC中提供了Condition对象, 用于让指定线程等待与唤醒, 按照预期顺序执行, 它必须和ReentrantLock重入锁配合使用 Conddition用于替代wait() / noti...

GQ_YIN日常记录 480

JUC并发编程第四章——LockSupport与线程中断

首先,一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,自己来决定自己的命运,所以,Thread.stop,Thread.suspend,Thread.resume都已经被废弃了其次,在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的协商机制----中断,也即中断标识协商机制中断只是一种协作协商机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自行实现。

qq_64064246的博客 1584

JUC-三种等待唤醒方式

synchronized的wait和notify wait方法会释放对象锁资源后进入等待队列,等待被唤醒 notify会唤醒等待队列中的单个线程 static Object objectLock=new Object();' new Thread(()->{ synchronized (objectLock){ System.out.println(Thread.currentThread().getName()+" come in");

HuaJi250的博客 432
上一篇: Leetcode链表刷题集合
下一篇: Spring中Bean的生命周期(三种版本循序渐进,简单易懂)
种花途。
博客等级 码龄10年 3粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值