java--线程的构建(来源疯狂java讲义)

首先在这里先介绍一下线程和进程的区别:

 

进程是一个程序一次运行的状态,进程是系统进行资源分配和调度的一个独立的单位。

进程包括三个特征:

独立性:进程是系统中独立存在的实体,它可以拥有自己独立的资源,每一个进程都拥有自己的私有地址空间,在没有经过进程本身允许的情况下,一个用户的进程不可以直接访问其他进程的地址空间。

动态性:进程和程序的区别在于,程序只是一个静态的指令集合。而进程是一个正在系统中活动的指令集合。在进程中加入了时间概念。进程具有自己的生命周期和各种不同的状态。这些概念在程序中都是不具备的。

并发性:多个进程可以在单个处理器上并发执行。多个进程之间不会互相影响。

 

并发性和并行性:这是两个不同的概念,并行性是指在同一时刻,有多条指令在多个处理器上同时执行,并发是指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。

 

其次,我们介绍一下线程的创建和启动:

 

线程的创建有:继承Thread类、实现Runnable接口、使用Callable和Future创建线程

1、继承Thread类:

它在java.lang.Thread   

原形为:

Public class Thread extends Object implements Runnable{}

它实现了Runnable 接口。

通过继承Thread类创建线程类步骤入下:

(1)、定义Thread类的子类,并重写run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。

(2)创建Thread子类的实例,即创建线程对象。

(3)调用线程对象的start()方法来启动该线程。

Start()方法,就是提醒一下该线程该运转了,然后立刻读取start()下面的代码。

 

下面列举一个通过继承Thread类来创建线程类。

 1 Public class FistThread extends Thread{
 2 
 3 Private int i;
 4 
 5 //重写run 方法,run方法的方法体就是线程的执行体
 6 
 7 Public void run(){
 8 
 9 For ( ; i<100 ; i++){
10 
11 //当线程类继承Thread类时,直接使用this即可以获取当前线程
12 
13 //Thread对象的getName()返回当先线程的名字
14 
15 //因此可以直接调用getName()方法返回当前线程的名字
16 
17 System.out.println ( getName() +” ”+i);
18 
19 }
20 
21 }
22 
23 Public static void main (String [] args){
24 
25 For(int i=0; i<100 ;i++){
26 
27 //调用Thread的currentThread()方法获取当前线程
28 
29 System.out.println(Thread.currentThread().getName()+ “ ”+i);
30 
31 If(i==20){
32 
33 //创建启动第一个线程
34 
35 new FirstThread().start();
36 
37 //创建启动第二个线程
38 
39 new FirstThread().start();
40 
41 } 
42 
43 }
44 
45 }
46 
47 }

 

使用继承Thread类的方法来创建线程类时,多个线程之间无法共享线程类的实例变量。

就上面的例子,相当于创建了两个线程,每个线程都能够运行100次。

2、实现Runnable 接口创建线程类:

实现Runnable接口来创建并启动多线程步骤如下:

(1)、定义Runnable接口的实现类,并重写该类接口的run方法,该run方法的方法体同样是该线程的执行体。

(2)、创建Runnable实现类的实例,并以此例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

(3)、调用线程对象start()方法来启动该线程。

 

下面列举一个通过实现Runnable接口创建线程类。

 1 Public class SecondThread implements Runnable{
 2 
 3 Private int i;
 4 
 5 Public void run (){
 6 
 7 For( ; i<100;i++){
 8 
 9 //当线程类实现Runnable接口时
10 
11 //如果想获得当前线程,只能用Thread.currentThread()方法
12 
13 System.out.println(Thread.currentThread().getName() +” ”+i);
14 
15 }
16 
17 }
18 
19 Public static void main(String []  args){
20 
21 For (int i=0;i<100;i++){
22 
23 System.out.println(Thread.currentThread().getName()+” ”+i);
24 
25 If(i==20){
26 
27 SecondThread st =new SecondThread();
28 
29 //通过new Thread(target,name)方法创建新线程
30 
31 New Thread (st,”新线程1”).start();
32 
33 New Thread(st,”新线程2”).start();
34 
35 }
36 
37 }
38 
39 }
40 
41 }

 

运行结果可以看出去两个线程i变量是连续的,也就是采用Runnable 接口的方式创建多个线程可以共享线程类的实例属性。

3、使用Callable 和 Future 创建线程

首先为什么出现这种方法。先看看前两个方法创建线程的缺点。

通过实现 Runnable 接口创建多线程时,Thread 类的作用就是把run方法包装成线程执行体,那么是否可以直接把任何方法包装成线程执行体?Java 目前是不行的。

Java 5 开始,Java 提供了Callable 接口,该接口是Runnable 的增强版,Callable 接口提供了一个call方法,该方法可以有返回值 也可以声明抛出异常。

注意:Callable 接口有泛型限制,Callable 接口里的泛型参数类型与call方法返回值类型相同。

创建并启动有返回值得线程的步骤如下:

(1)、创建Callable 接口的实现类,并实现call()方法,该call方法作为线程执行体,且该call方法有返回值。

(2)创建Callable实现类的实例,并使用FutureTask类来包装Callable对象,该FutureTask 对象封装了该Callable对象的call方法的返回值。

(3)使用FutureTask 对象作为Thread 对象的target  来创建并启动线程。

(4)调用FutureTask 对象的get方法来获得子线程执行结束之后的返回值。

下面程序通过实现Callable 接口来实现线程类,并启动该线程:

 1 import java.util.concurrent.Callable;
 2 
 3 import java.util.concurrent.FutureTask;
 4 
 5 public class ThirdThread implements Callable<Integer>
 6 
 7 {
 8 
 9 //实现call()方法,作为线程的执行体
10 
11 public Integer call(){
12 
13 int i=0;
14 
15 for( ;i<20;i++){
16 
17 System.out.println(Thread.currentThread().getName()+"的循环变量 i的值为:"+i);
18 
19 }
20 
21 return i;
22 
23 }
24 
25 public static void main(String[] args){
26 
27 //创建Callable 对象
28 
29 ThirdThread rt=new ThirdThread();
30 
31 //使用FutureTask来包装Callable对象
32 
33 FutureTask<Integer> task= new FutureTask<Integer>(rt);
34 
35 for(int i=0 ;i<20;i++){
36 
37 System.out.println(Thread.currentThread().getName()+"的循环变量为:"+i);
38 
39 if(i==5){
40 
41 //开始线程
42 
43 new Thread(task,"有返回值的线程").start();
44 
45 }
46 
47 }try
48 
49 {
50 
51 System.out.println("子线程的返回值为:"+task.get());
52 
53 }
54 
55 catch (Exception e)
56 
57 {
58 
59 e.printStackTrace();
60 
61 }
62 
63 }
64 
65  
66 
67 }
View Code

 

记住需要import java.util.concurrent.Callable;  import java.util.concurrent.FutureTask;

程序最后调用FutureTask 对象的get方法来返回call方法的返回值------该方法将导致主线程被阻塞,直到call方法结束并返回为止。

如果代码为下面这样:

 1 import java.util.concurrent.Callable;
 2 
 3 import java.util.concurrent.FutureTask;
 4 
 5 public class ThirdThread implements Callable<Integer>
 6 
 7 {
 8 
 9 //实现call()方法,作为线程的执行体
10 
11 public Integer call(){
12 
13 int i=0;
14 
15 for( ;i<20;i++){
16 
17 System.out.println(Thread.currentThread().getName()+"的循环变量 i的值为:"+i);
18 
19 }
20 
21 return i;
22 
23 }
24 
25 public static void main(String[] args){
26 
27 //创建Callable 对象
28 
29 ThirdThread rt=new ThirdThread();
30 
31 //使用FutureTask来包装Callable对象
32 
33 FutureTask<Integer> task= new FutureTask<Integer>(rt);
34 
35 for(int i=0 ;i<20;i++){
36 
37 System.out.println(Thread.currentThread().getName()+"的循环变量为:"+i);
38 
39 if(i==5){
40 
41 //开始线程
42 
43 new Thread(task,"有返回值的线程").start();
44 
45 try{
46 
47 System.out.println("子线程的返回值为:"+task.get());
48 
49 }
50 
51 catch (Exception e)
52 
53 {
54 
55 e.printStackTrace();
56 
57 }
58 
59 }
60 
61  
62 
63 }
64 
65 }
66 
67  
68 
69 }

 

那么输出结果为:

main的循环变量为:0

main的循环变量为:1

main的循环变量为:2

main的循环变量为:3

main的循环变量为:4

main的循环变量为:5

有返回值的线程的循环变量 i的值为:0

有返回值的线程的循环变量 i的值为:1

有返回值的线程的循环变量 i的值为:2

有返回值的线程的循环变量 i的值为:3

有返回值的线程的循环变量 i的值为:4

有返回值的线程的循环变量 i的值为:5

有返回值的线程的循环变量 i的值为:6

有返回值的线程的循环变量 i的值为:7

有返回值的线程的循环变量 i的值为:8

有返回值的线程的循环变量 i的值为:9

有返回值的线程的循环变量 i的值为:10

有返回值的线程的循环变量 i的值为:11

有返回值的线程的循环变量 i的值为:12

有返回值的线程的循环变量 i的值为:13

有返回值的线程的循环变量 i的值为:14

有返回值的线程的循环变量 i的值为:15

有返回值的线程的循环变量 i的值为:16

有返回值的线程的循环变量 i的值为:17

有返回值的线程的循环变量 i的值为:18

有返回值的线程的循环变量 i的值为:19

子线程的返回值为:20

main的循环变量为:6

main的循环变量为:7

main的循环变量为:8

main的循环变量为:9

main的循环变量为:10

main的循环变量为:11

main的循环变量为:12

main的循环变量为:13

main的循环变量为:14

main的循环变量为:15

main的循环变量为:16

main的循环变量为:17

main的循环变量为:18

main的循环变量为:19

也就验证了上面的情况  get方法会使主线程阻断。直到call方法结束后。才调用主线程。

 

创建线程的三种方式对比:

 

采用实现Runnable Callable 接口的方式创建多线程——

线程类只是实现了Runnable 接口或Callable 接口 ,还可以继承其他类。

在这种方式下,多线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU 、代码、和数据分开。

劣势是:编程稍稍复杂,如果需要访问当前线程,则必须使用Thread.currentThred()方法。

采用继承Thread类的方式创建多线程————

优势:编写简单,如果需要访问当前线程,则无须使用Thread.currentThread()方法。直接使用this 即可获得当前线程。

劣势:因为线程只能继承一个父类。所以它继承了Thread 不能在继承其他的父类了。

 

转载于:https://www.cnblogs.com/teng-IT/p/4439084.html

《疯狂Java讲义精粹(第2版)》深度学习指导 除了使用Java提供的标准异常类,我们还可以根据需要创建自己的异常类,这被称为自定义异常。自定义异常通常用于表示特定的业务错误或异常情况。创建自定义异常时,我们通常会继承Exception类或其子类。自定义异常一般包含两个构造函数:一个是无参构造函数,另一个是接收错误信息的构造函数。这有助于在异常处理时获取更多的错误上下文信息。// 自定义异常类示例// 构造函数,接收错误信息// 无参构造函数super();// 使用自定义异常的示例try { 阅读详情

相关推荐

SIMULIA-Simpack 2022x新功能介绍

增加库伦摩擦类型力元95 Coulomb Friction增加了3种新的摩擦方向类型用于模拟平面、圆柱和球面摩擦。针对平移和旋转摩擦改进了滑动到粘着过渡阶段的检测,增加一个参数定义两种不同的滑移-粘滞过渡模式,即“Unloaded stick stiffness”和“Preload stick with last slip”。新增加124'Applied Load’力元允许用户将力或扭矩作为恒定值或通过激励元素施加到To Marker点上。该力元建模操作方便,效率高。支持线性柔性体装配。

crystalzhan的博客 1047

Thread.currentThread().getName与this.getName()理解

在看Java多线程编程核心技术,对Thread.currentThrad.getName()与this.getName运行结果产生了困惑,看了网上一些博客解释,自己也产生了些许想法。 线程类: public class MyThread extends Thread{ public MyThread() { System.out.println("构造方法"); Syste...

大鹏视界U 727

IAR9.30以上版本安装、注册、新建工程和配置过程详细介绍

IAR 一般是指一款嵌入式软件的集成开发环境,类似于 MDK-Keil 这款软件。IAR 对于不同的内核处理器,是对应不同的 IAR 软件的,IAR 到目前为止支持大部分的MCU,比如8051系列、ARM架构系列、MSP430系列、AVR系列等等这些常用的芯片架构。对于 ARM 架构的芯片,有对应的 IAR Embedded Workbench for ARM 软件平台,因为我主要是使用 ARM 架构芯片,下面安装、注册和使用都是基于这个版本进行介绍的。

luobeihai的博客 6万+

Java多线程篇

测试Thread中的常用方法:1.start():启动当前线程;调用当前线程的run()2.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中3.currentThred():静态方法,返回执行当前代码的线程4.getName():获取当前线程的名字5.setName():设置当前线程的名字6.yield():释放当前cpu的执行权7.join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完成以后线程a才结束阻塞状态。8.stop

qq_59336423的博客 148

Win10 / Win11 启用 Hyper-V 虚拟机详细教程(图文+命令行全攻略)

摘要:本文详细介绍Windows10/11系统启用Hyper-V虚拟化平台的方法,包含专业版/企业版的图形界面和PowerShell命令行操作,以及家庭版通过脚本强制启用的特殊方案。内容涵盖版本支持对比、操作步骤图解、常见问题解答和性能优化建议,帮助开发者快速搭建虚拟化环境进行多系统测试。附微软官方文档参考链接和详细操作示意图。

ElioXu 7082

echarts 生成中国陕西省份(或其他省份)的地图,大屏使用

效果图: 一、首先第一步需要下载echarts和获取到陕西身份的地图信息。 1.下载echarts链接(官网): Apache ECharts 2.生成指定省份的地图数据信息,数据可以在阿里云获取。 DataV.GeoAtlas地理小工具系列 如图,点击左圈需要的省份,这里我选择的是陕西省,然后点击右圈复制下载链接,得到一个json格式的数据,可以在json转换网站转成js格式。 Json在线解析格式化-Json在线校验Json格式化压缩-Jsons在线工具 转成js格.

PrimaryColor 3890

java的Thread的方法_Java Thread currentThread()方法

Java Thread currentThread()方法java.lang.Thread.currentThread()方法返回一个引用到当前正在执行的线程对象。1 语法public static Thread currentThread()2 参数无3 返回值此方法返回当前正在执行的线程。4 示例package com.yiidian;/*** 一点教程网: http://www.yiidi...

weixin_32645173的博客 1003

银河麒麟高级服务器V11操作系统安装部署zabbix监控平台的实操保姆级教程

本文详细介绍了在《银河麒麟高级服务器V11上安部署Zabbix监控系统的全过程》涵盖了zabbix监控系统涉及到的所有软件安装、参数优化、服务启动验证及防火墙配置等一系列实操。其中关于安装过程报错undefined symbol: usmAES256CiscoPrivProtocol;ares_reinit等依赖库问题进行了详细记录与分析解决;还提供了Web前端中文显示修复方案和Admin密码修改方法。实现监控平台的100%部署上线,实现对业务系统的实时监控,保证业务的稳定运行。

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 532

java多线程中Thread.currentThread() 和 this 的区别

1.java多线程中Thread.currentThread() 和 this 的区别: /** * @Description: java多线程中Thread.currentThread() 和 this 的区别 * @Author: likun * @Date: 2021/1/26 */ public class T { public static void main(String[] args) { T1 t1 = new T1("T1"); Thr

freedomflow的博客 195

caverdock如何使用,一文给你多方案教学!

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值。

**My Coding Family** 1390

10、智慧变电站 - 加载vue大屏元素(整体效果)

这一篇文章非常简单,但是也非常出效果阅读前面几篇文章,都可以看到有顶部、左侧、右侧的面板,主要我不会录gif图片,大屏元素面板还有一些动态加载的效果。 vue的transition标签 Vue 提供了 transition 的封装组件,可以给任何元素和组件添加进入/离开过渡;在进入/离开的过渡中,会有 6 个 class 切换:v-enter 、v-enter-active 、v-enter-to 、v-leave 、v-leave-active 、v-leave-to。我们正好使用这个特性来达到面板进入

github_39988036的博客 1041

【社区图书馆】疯狂 Java 讲义:但凡种种,不一而足

疯狂Java讲义(第6版)(上下册)》是由著名IT畅销书作家李刚所著的关于Java语言的权威书籍。本书的新版本在原有基础上增加了更多实例和案例,使得读者更容易理解和掌握该编程语言。此书主要面向想要学习Java编程的初、中级程序员以及对编程有兴趣的人群。该书在国内外广受好评,是Java学习必备之书。这一段真的是太官方了,一般你随便看一个书籍介绍,基本都会来上这么一段风格的文章,不管书怎样,先氛围搞起来的意思。

我在山城重庆,我希望能为这片软件沙漠地带贡献自己的一滴水,Stay tuned! 1947

【C语言】一文搞懂C语言文件操作

读写文件、文件相关库函数详解、文件缓冲区介绍

StackFrame 5661

疯狂java讲义第6版_疯狂java讲义第6版

疯狂java讲义第6版下载!疯狂java讲义第6版pdf是李刚打造的经典java编程图书的最新版,为了帮助更多的读者能真正掌握Java编程,感受到Java语言的魅力,领会到Java编程的快乐,作者根据多年来的Java授课经验,精心编写了本书,喜欢可以下载阅读!疯狂java讲义第6版pdf简介《疯狂Java讲义》是李刚所著的一本图书!本书并不是一个简单的Java入门教材,也不是一门“闭门造车”式的J...

weixin_33726568的博客 3796

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

学习《疯狂Java讲义第4版》PDF+代码+课件+面试题分析

学习java选择了《疯狂java讲义》最新的第四版,用了两个多月时间看完,一边阅读,一边敲代码。对Java有了不少新的认识。书中实例清晰明了,讲解也是娓娓道来。Java可以编写图形桌面系统,可以编写游戏,可以操作文件系统,可以进行网络传输。案例能够讲解各种Java基础知识。有意思,能够理解一些知识,敲代码,运行代码,感受代码的魅力!继续努力,学习与实践相结合!读书与实践相结合! 《疯狂Java讲...

weixin_30270561的博客 5704

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

疯狂Java讲义第六版资源文件:Java学习者的必备工具

疯狂Java讲义第六版资源文件:Java学习者的必备工具 【下载地址】疯狂Java讲义第六版资源文件介绍 疯狂Java讲义第六版资源文件为Java学习者提供了全面的学习支持。该资源包含完整的示例代码、实践项目源码及配套教学视频,覆盖Java编程的各个方面,如基本语法、面向对象编程、异常处理、集合框架、多线程、网络编程和图...

gitblog_06792的博客 674

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

疯狂java讲义第四章习题答案

1、使用循环输出九九乘法表。

yaoguaiba579567的博客 1574

《疯狂java讲义》读后感

《疯狂java讲义·第三版》,全书共851页,18章。 目录如下: 第1章 Java语言概述与开发环境 第2章 理解面向对象 第3章 数据类型和运算符 第4章 流程控制与数组 第5章 面向对象(上) 第6章 面向对象(下) 第7章 Java基础类库 第8章 Java集合 第9章 泛型 第10章 异常处理 第11章 AWT编程 第12章 Swing编程 第13章 MySQL数据库与JDBC...

aihuanshang9340的博客 376

Java疯狂讲义

目录 第一章:java语言概述和开发环境: 第二章:理解面对对象: 第三章:数据类型和运算符: 第四章:流程控制和数组: 第五章:面对对象: 第八章:集合框架: 第十章:异常处理: 第十六章:多线程: 第一章:java语言概述和开发环境: JVM:Java虚拟机,负责执行指令,管理数据,内存和寄存器。 JDK:java开发安装所需要的。 JRE:包含JVM。 垃圾回...

若叶知秋的博客 4478

java下载pdf6_疯狂java讲义第6版 电子版(pdf格式)

疯狂java讲义第6版pdf是李刚打造的经典java编程图书的最新版,为了帮助更多的读者能真正掌握Java编程,感受到Java语言的魅力,领会到Java编程的快乐,作者根据多年来的Java授课经验,精心编写了本书,喜欢可以在WWW.11684.COM下载阅读!疯狂java讲义第6版pdf简介《疯狂Java讲义》是李刚所著的一本图书!本书并不是一个简单的Java入门教材,也不是一门“闭门造车”式的J...

weixin_42407617的博客 8220

疯狂Java讲义第六版资源文件介绍

疯狂Java讲义第六版资源文件介绍 【下载地址】疯狂Java讲义第六版资源文件介绍 疯狂Java讲义第六版资源文件为Java学习者提供了全面的学习支持。该资源包含完整的示例代码、实践项目源码及配套教学视频,覆盖Java编程的各个方面,如基本语法、面向对象编程、异常处理、集合框架、多线程、网络编程和图形用户界面编程等。无论...

gitblog_06758的博客 437

《疯狂的JAVA讲义》笔记-第8章集合

《疯狂的JAVA讲义》笔记-第8章集合 讲述集合的各种特性以及应用场景

klli15的博客 287

《疯狂java讲义》第16章 多线程

本章将会详细介绍Java多线程编程的相关方面,包括创建、启动线程、控制线程,以及多线程的同步操作,并会介绍如何利用Java内建支持的线程池来提高多线程性能。

weixin_43806049的博客 510

java疯狂讲义 16章多线程习题

java疯狂讲义 16章多线程习题习题1:刚开始的思路:总结:改进1:总结1:改进2: 习题1: 写2个线程,其中一个线程打印1-52,另一个线程打印A-Z,打印顺序应该是12A34B56C……5152Z。该习题需要利用多线程通信的知识。 刚开始的思路: 既然需要两个线程打印,那就写两个类,分别继承Thread,里面的run方法写各自的打印逻辑;但是又想?这么写,该如何通信呢。。。。。。通信...

qq_34782535的博客 594

《疯狂java讲义》学习(46):线程池

1.线程池 系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互。在这种情形下,使用线程池可以很好地提高短暂的线程时,更应该考虑使用线程池。 与数据库连接池类似的是,线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象或Callable对象传给线程池,线程池就会启动一个线程来执行他们的run()或call()方法,当run()或call()方法执行结束后,该线程并不会死亡...

泛泛之素 601
下一篇: 线程问题—一个线程怎么调出另外一个线程的结果。
aixirang3421
博客等级 码龄11年 0粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值