黑马程序员_笔迹十一_关于多线程学习

----------android培训java培训期待与您交流!----------

进程与线程的简介

    进程是程序的一次动态执行,它经历了从代码加载,执行到执行完毕的一个完整的过程,这个过程也是进程本身从产生,发展到最终消亡的过程。多进程操作系统能同时运行多个进程(程序),由于cpu具备分时机制,所以每个进程都能循环获得自己的cpu时间片。由于cpu执行速度快,使得所有程序好像是同时运行一样.

    多线程是实现并发机制的一种有效手段。进程和线程一个,都是实现并发的一个基本单位。线程是比进程更小的执行单位,线程是在进程的基础上进行的进一步划分。所谓的多线程是指一个进程在执行过程中,可以产生多个线程,这些线程可以同时存在,同时运行,一个进程可能包含多个同时执行的线程,

 

java中线程的实现

java中,要想实现多线程有2中代码,一种是继承Thread类,另外一种是实现Runnable接口.

 

继承Thread

Thread类实在java.lang包中定义的,一个类只要继承了Thread类,此类就称为多线程操作类。在Thread类,必须明确的覆写Thread类中的run()方法,此方法称为线程的主体

语法定义

class 类名称 extends Thread{//继承Thread

    属性......;//类中定义属性

    方法......;//类中定义的方法

    public void run(){//覆写Thread类中的run方法,此方法时线程的主体

    线程主体;

}

    }

常用方法

 Thread.currentThread()  获取当前线程对象

  getName()  获取线程名称

  setName()  设置线程名称

  start()  使该线程开始执行;Java虚拟机调用该线程的 run 方法。

 

实例代码

class MyThread extendsThread{     // 继承Thread类,作为线程的实现类实例代码

     private Stringname ;          //表示线程的名称
     public MyThread(String name){
          this.name = name;          //
通过构造方法配置name属性
     }
     public void run(){     //
覆写run()方法,作为线程的操作主体
          for(inti=0;i<10;i++){
              System.out.println(name + "
运行,i = " + i) ;
          }
     }
};
public class Demo{
     public static void main(String args[]){
          MyThread mt1 = newMyThread("
线程A ") ;     //实例化对象
          MyThread mt2 = newMyThread("
线程B ") ;     //实例化对象
          mt1.start();     //
调用线程主体
          mt2.start();     //
调用线程主体
     }
};

结果:

线程B 运行,i = 3

线程A 运行,i = 0

线程B 运行,i = 4

..........

...........

(输出结果每次都不一样,到底哪个先运行,是系统调度后做出的决定,谁先拿到cpu的执行权,谁先运行)

PS:在启动多线程时,必须通过start()方法启动,因为线程的运行需要本机操作系统的支持

 

实现Runnable接口方式实现多线程

java中也可以通过实现Runnable接口的方式实现多线程,Ruannable中只定义了一个抽象方法

public void run();

 

使用Runnable接口实现多线程的格式如下

class 类名称 implements Runnable{//实现Runnable接口

    属性......;//类中定义属性

    方法......;//类中定义的方法

    public void run(){//覆写Thread类中的run方法,此方法时线程的主体

    线程主体;

 

}

代码实例

class MyThread implements Runnable{     //实现Runnable接口,作为线程的实现类
     private String name;          //
表示线程的名称
     public MyThread(String name){
          this.name = name;          //
通过构造方法配置name属性
     }
     public void run(){     //
覆写run()方法,作为线程的操作主体
          for(inti=0;i<10;i++){
              System.out.println(name + "
运行,i = " + i) ;
          }
     }
};
public class RunnableDemo01{
     public static void main(String args[]){
          MyThread mt1 = newMyThread("
线程A ") ;     //实例化对象
          MyThread mt2 = newMyThread("
线程B ") ;     //实例化对象
          Thread t1 = newThread(mt1) ;          //
实例化Thread类对象
          Thread t2 = newThread(mt2) ;          //
实例化Thread类对象
          t1.start();     //
启动多线程
          t2.start();     //
启动多线程
     }
};

 

PS:以上两种方式,无论是员工那种方式,最终都必须依靠Thread类才能启动多线程

 

Thread类和Runnable接口的比较

1 实现了Runnable接口适合多个程序代码的线程去处理同一资源

2 可以避免由于java的但继承特性带来的局限

3 增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的

 

代码实例---多个线程执行卖票

class MyThread implements Runnable{     //继承Thread类,作为线程的实现类

    private int ticket = 5;          // 表示一共有5张票

    public void run(){     //覆写run()方法,作为线程的操作主体

         for (int i=0;i<100;i++){

              if (this .ticket >0){

                  System. out .println("卖票:ticket = " + ticket --) ;//每卖掉一张票,票数减一

             }

        }

    }

};

public class Demo{

    public static void main(String args[]){

        MyThread mt = new MyThread();     //实例化对象

         new Thread(mt).run();     //调用线程主体

         new Thread(mt).run();     //调用线程主体

         new Thread(mt).run();     //调用线程主体

    }

};

结果:卖票:ticket = 5

卖票:ticket = 4

卖票:ticket = 3

卖票:ticket = 2

卖票:ticket = 1

 

线程的状态

任何线程一般都具有5种状态,既创建()就绪(执行start()方法)运行(获得cpu执行权,运行run()方法)阻塞(sleep(),wait()),死亡(调用stop方法或者run方法执行结束)

 

一些常用的线程操作方法

 

取得和设置线程名称

class MyThread implements Runnable{     //实现Runnable接口

    public void run(){     //覆写run()方法

         for(int i=0;i<3;i++){

             System.out.println(Thread.currentThread().getName()

                       + "运行,i = " +i) ;     //取得当前线程的名字

        }

    }

};

public class Demo{

    public static void main(String args[]){

        MyThread mt = new MyThread();     //实例化Runnable子类对象

         new Thread(mt).start();          //系统自动设置线程名称

         new Thread(mt,"线程A" ).start();          //手工设置线程名称

      

    }

};

结果:Thread-0运行,i = 0

Thread-0运行,i = 1

Thread-0运行,i = 2

线程A运行,i = 0

线程A运行,i = 1

线程A运行,i = 2

 

判断线程是否启动

class MyThread implements Runnable{ //实现Runnable接口

    public void run(){  //覆写run()方法

         for(int i=0;i<3;i++){

            System. out.println(Thread.currentThread().getName()

                    + "运行,i = " + i) ;   //取得当前线程的名字

        }

    }

};

public class Demo{

    public static void main(String args[]){

        MyThreadmt = new MyThread() ;  //实例化Runnable子类对象

        Threadt = new Thread(mt,"线程" );       //实例化Thread对象

        System. out.println("线程开始执行之前 --> " + t.isAlive()) ;   //判断是否启动

        t.start();  //启动线程

        System. out.println("线程开始执行之后 --> " + t.isAlive()) ;   //判断是否启动

         for(int i=0;i<3;i++){

            System. out.println(" main运行 --> " + i) ;

        }

         //以下的输出结果不确定

        System. out.println("代码执行之后 --> " + t.isAlive()) ;   //判断是否启动

        

    }

};

结果:

线程开始执行之前 --> false

线程开始执行之后 --> true

 main运行 --> 0

线程运行,i = 0

 main运行 --> 1

 main运行 --> 2

线程运行,i = 1

代码执行之后 --> true

线程运行,i = 2

 

线程的强制运行

在线程操作中,可以使用join()方法让一个线程强制运行,此时其他线程无法运行,必须等待此线程完成之后才可以继续运行

class MyThread implements Runnable{ //实现Runnable接口

    public void run(){  //覆写run()方法

         for(int i=0;i<5;i++){

            System. out.println(Thread.currentThread().getName()

                    + "运行,i = " + i) ;   //取得当前线程的名字

        }

    }

};

public class Demo{

    public static void main(String args[]){

        MyThreadmt = new MyThread() ;  //实例化Runnable子类对象

        Threadt = new Thread(mt,"join()方法测试线程" );       //实例化Thread对象

        t.start();  //启动线程

         for(int i=0;i<5;i++){

             if(i>1){//如果i>1,就让t线程,获得cpu强制执行,此时main线程,要等待

                 try{

                    t.join();   //线程强制运行

                } catch(InterruptedException e){}

            }

            System. out.println("Main线程运行 --> " + i) ;

        }

    }

};

结果:

Main线程运行 --> 0

Main线程运行 --> 1

join()方法测试线程运行,i = 0

join()方法测试线程运行,i = 1

join()方法测试线程运行,i = 2

join()方法测试线程运行,i = 3

join()方法测试线程运行,i = 4

Main线程运行 --> 2

Main线程运行 --> 3

Main线程运行 --> 4

 

线程的休眠

在程序中允许一个线程进行暂时的休眠,直接使用Thread.sleep()方法即可实现线程的休眠

class MyThread implements Runnable{ //实现Runnable接口

    public void run(){  //覆写run()方法

         for(int i=0;i<3;i++){

             try{

                    Thread. sleep(1000);    //线程休眠1

            } catch(InterruptedException e){}

            System. out.println(Thread.currentThread().getName()

                    + "运行,i = " + i) ;   //取得当前线程的名字

        }

    }

};

public class Demo{

    public static void main(String args[]){

        MyThreadmt = new MyThread() ;  //实例化Runnable子类对象

        Threadt = new Thread(mt,"线程" );       //实例化Thread对象

        t.start();  //启动线程

    }

};

 结果:

线程运行,i = 0

线程运行,i = 1

线程运行,i = 2

每间隔一秒钟,打印一次。

 

线程的中断

当一个线程运行时,另外一个线程可以直接通过interrupt方法中断其运行状态

 

class MyThread implements Runnable{ //实现Runnable接口

    public void run(){  //覆写run()方法

        System. out.println("1、进入run()方法" ) ;

         try{

                 Thread.sleep(10000);    //线程休眠10

                System. out.println("2、已经完成了休眠" ) ;

        } catch(InterruptedException e){

            System. out.println("3、休眠被终止" ) ;

             return ; //返回调用处

        }

        System. out.println("4run()方法正常结束" ) ;

    }

};

public class Demo{

    public static void main(String args[]){

        MyThreadmt = new MyThread() ;  //实例化Runnable子类对象

         Thread t = new Thread (mt,"线程" );       //实例化Thread对象

        t.start();  //启动线程

         try{

                 Thread.sleep(2000);    //线程休眠2

        } catch(InterruptedException e){

            System. out.println("3、休眠被终止" ) ;

        }

        t.interrupt();  // 线程休眠2秒,中断线程执行

    }

};

 

结果:1、进入run()方法

3、休眠被终止

 

线程的优先级

 

java的线程操作中,所有的线程运行前都会保持就绪状态,那么此时,哪个线程的游戏优先级高,哪个线程就有可能会先被执行

 

lass MyThread implements Runnable{ //实现Runnable接口

    public void run(){  //覆写run()方法

         for(int i=0;i<5;i++){

             try{

                    Thread. sleep(500); //线程休眠

            } catch(InterruptedException e){}

            System. out.println(Thread.currentThread().getName()

                    + "运行,i = " + i) ;   //取得当前线程的名字

        }

    }

};

public class Demo{

    public static void main(String args[]){

        Threadt1 = new Thread(new MyThread(),"线程A" ) ;   // 实例化线程对象

        Threadt2 = new Thread(new MyThread(),"线程B" ) ;   // 实例化线程对象

        Threadt3 = new Thread(new MyThread(),"线程C" ) ;   // 实例化线程对象

        t1.setPriority(Thread. MIN_PRIORITY) ;    //优先级最低

        t2.setPriority(Thread. MAX_PRIORITY) ;    //优先级最低

        t3.setPriority(Thread. NORM_PRIORITY) ;    //优先级最低

        t1.start();     //启动线程

        t2.start();     //启动线程

        t3.start();     //启动线程

    }

};

 

结果:线程B运行,i = 0

线程A运行,i = 0

线程C运行,i = 0

线程B运行,i = 1

线程A运行,i = 1

线程C运行,i = 1

线程B运行,i = 2

线程A运行,i = 2

线程C运行,i = 2

线程B运行,i = 3A运行,i = 3

线程C运行,i = 3

线程B运行,i = 4

线程A运行,i = 4

线程C运行,i = 4

PS:一定要注意,并非线程的优先级高就一定会先执行,哪个线程先执行将由cpu的调度决定

 

 

线程的礼让

 

在线程的操作中,使用yield()方法将一个线程的操作暂时让给其他的线程执行

class MyThread implements Runnable{ //实现Runnable接口

    public void run(){  //覆写run()方法

         for(int i=0;i<3;i++){

             try{

                Thread. sleep(500);//休眠0.5

            } catch(Exception e){}

            System. out.println(Thread.currentThread().getName()

                    + "运行,i = " + i) ;   // 取得当前线程的名字

             if(i==2){//i==2时,线程进行礼让

 

                System. out.print("线程礼让:" ) ;

                 Thread.currentThread ().yield() ;    //线程礼让

            }

        }

    }

};

public class Demo

{

    public static void main(String args[]){

        MyThreadmy = new MyThread() ;  //实例化MyThread对象

        Threadt1 = new Thread(my,"线程A" ) ;

        Threadt2 = new Thread(my,"线程B" ) ;

        t1.start();

        t2.start();

    }

};

 

结果:

线程B运行,i = 0

线程A运行,i = 0

线程B运行,i = 1

线程A运行,i = 1

线程B运行,i = 2

线程礼让:线程A运行,i = 2

线程礼让:线程B运行,i = 3

线程A运行,i = 3

线程B运行,i = 4

线程A运行,i = 4

 

PS:join:当A线程执行到B线程的join()方法时,A就会等待,等待B线程执行完,A才会执行。join可以用来临时加入线程执行   

 

 

同步与死锁

一个多线程的程序如果是通过Runnable接口实现的,则意味着类中的属性将要被多个线程共享,那么这样一来就会造成一个问题,如果这多个线程要操作同一资源有可能出现资源的同步问题。

 

代码实例

class MyThread implements Runnable{

    private int ticket = 5 ;    // 假设一共有5张票

    public void run(){

         for(int i=0;i<100;i++){

             if(ticket >0){   //还有票

                 try{

                    Thread. sleep(500); //加入延迟。线程执行时,就有可能出现资源同步问题

                } catch(InterruptedException e){

                    e.printStackTrace();

                }

                System. out.println("卖票:ticket = " + ticket-- );

            }

        }

    }

};

public class Demo{

    public static void main(String args[]){

        MyThreadmt = new MyThread() ;  //定义线程对象

        Threadt1 = new Thread(mt) ;    //定义Thread对象。执行卖票

        Threadt2 = new Thread(mt) ;    // 定义Thread对象。执行卖票

        Threadt3 = new Thread(mt) ;    // 定义Thread对象。执行卖票

        t1.start();

        t2.start();

        t3.start();

    }

};

 

结果:

卖票:ticket = 5

卖票:ticket = 4

卖票:ticket = 3

卖票:ticket = 2

卖票:ticket = 1

卖票:ticket = 0

卖票:ticket = -1有可能会出现ticket是负数的情况,属于资源同步问题

 

如果要解决这样的问题,就必须使用同步。所谓的同步,就是指多个操作在同一时间段内只能有一个程序运行,其他线程都要等待此线程完成之后才可能继续执行

使用同步解决资源问题

解决资源共享的同步问题,可以使用同步代码块和同步方法两种方式来完成

 

同步代码块

synchronized(同步对象){

需要同步的代码

}

 

class MyThread implements Runnable{

    private int ticket = 5 ;    // 假设一共有5张票

    public void run(){

         for(int i=0;i<100;i++){

            synchronized(this )//要对当前对象进行同步,关键字synchronized 

                 if(ticket >0){   //还有票

                     try{

                        Thread. sleep(300); //加入延迟

                    } catch(InterruptedException e){

                        e.printStackTrace();

                    }

                    System. out.println("卖票:ticket = " + ticket -- );

                }

            }

        }

    }

};

public class Demo{

    public static void main(String args[]){

        MyThreadmt = new MyThread() ;  //定义线程对象

        Threadt1 = new Thread(mt) ;    //定义Thread对象

        Threadt2 = new Thread(mt) ;    //定义Thread对象

        Threadt3 = new Thread(mt) ;    //定义Thread对象

        t1.start();

        t2.start();

        t3.start();

    }

};

结果:卖票:ticket = 5

卖票:ticket = 4

卖票:ticket = 3

卖票:ticket = 2

卖票:ticket = 1

 

同步方法

除了可以将需要的代码块设置成同步代码块快,也可以使用synchronized关键字将一个方法声明成同步方法

synchronized 方法返回值方法名称(参数列表){

}

 

class MyThread implements Runnable{

    private int ticket = 5 ;    // 假设一共有5张票

    public void run(){

         for(int i=0;i<100;i++){

             this.sale() ;   //调用同步方法

        }

    }

    public synchronized void sale(){    //声明同步方法

         if(ticket >0){   //还有票

             try{

                Thread. sleep(300); //加入延迟

            } catch(InterruptedException e){

                e.printStackTrace();

            }

            System. out.println("卖票:ticket = " + ticket-- );

        }

 

    }

};

public class Demo{

    public static void main(String args[]){

        MyThreadmt = new MyThread() ;  //定义线程对象

        Threadt1 = new Thread(mt) ;    //定义Thread对象

        Threadt2 = new Thread(mt) ;    //定义Thread对象

        Threadt3 = new Thread(mt) ;    //定义Thread对象

        t1.start();

        t2.start();

        t3.start();

    }

};

结果:卖票:ticket = 5

卖票:ticket = 4

卖票:ticket = 3

卖票:ticket = 2

卖票:ticket = 1

 

线程操作的经典案例学习-----生产者和消费者

 生产者生产出信息后将其放到一个区域中,消费者从区域取出数据,但是因为涉及到线程运行的不确定性,可能会存在以下2个问题

1 假设生产者线程刚向数据存储空间添加了信息的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程将把会把信息的名称和上一个信息的内容联系在一起

2 生产者放了若干次的数据,消费者才开始取数据,或者是,消费者取完一个数据后,还没等到射给生产者放入新的数据,又重复取出已经去过出的数据

通过代码,来分析上述问题的解决方式。主要是用到Object中,对线程的一些支持方法。

wait()notify()notifyAll();,都使用在同步中,因为都要对持有监视器(锁)的线程操作,所以要使用在同步中,而只有在同步中才具体锁。定义在Object类中,是因为这些方法在操作同步中的线程时,都必须要标识它们所操作线程持有的锁。锁上的被等待线程,只可以被同一个锁上的notifynotifyAll唤醒,不可以被不同锁中的线程notifynotifyAll唤醒。也就是说,等待和唤醒必须是同一个锁而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。

一般来说,所有等待的线程会按照顺序进行排列,如果现在使用了notify()方法,则会唤醒第一个等待的线程,而如果使用了notifyAll方法,则会唤醒所有的等待线程,哪个线程优先级高,哪个线程就有可能先执行

 

class Info{     //定义信息类

     private String name = "上午对应---";     //定义name属性

     private String content = "am" ;          //定义content属性

     private boolean flag = false ;     // 设置一个标志位为boolean类型变量,如果标志位的内容为true,则表示可以生产,但是不能取走,此时线程执行到了消费者线程则应该等待。如果标志位为false,则表示可以取走,但是不能生产,如果生产者线程运行,则应该等待

     public synchronized void set(String name,String content){//生产者线程

          if(!flag ){//如果flagfalse,表示消费者可以取走,此时生产者需要等待

               try{

                    super.wait() ;//生产者等待消费者取走数据 

              } catch(InterruptedException e){

                   e.printStackTrace() ;

              }

         }

          this.setName(name) ;     //设置名称

          try{

              Thread. sleep(300) ;

         } catch(InterruptedException e){

              e.printStackTrace() ;

         }

          this.setContent(content);     //设置内容

          flag  = false ;     //改变标志位,表示可以取走

          super.notify() ;

     }

     public synchronized void get(){

          if(flag ){//flagtrue,表示可以生产,此时消费者线程等待

               try{

                    super.wait() ;

              } catch(InterruptedException e){

                   e.printStackTrace() ;

              }

         }

          try{//加入延迟操作

              Thread. sleep(300) ;

         } catch(InterruptedException e){

              e.printStackTrace() ;

         }

         System. out.println(this .getName() +

               " --> " + this .getContent()) ;

          flag  = true ;     //改变标志位,表示可以生产

          super.notify() ;

     }

     public void setName(String name){

          this.name = name ;

     }

     public void setContent(String content){

          this.content = content ;

     }

     public String getName(){

          return this .name ;

     }

     public String getContent(){

          return this .content ;

     }

};

class Producer implements Runnable{     //通过Runnable实现多线程

     private Info info = null ;          //保存Info引用

     public Producer(Info info){

          this.info = info ;

     }

     public void run(){

          boolean flag = false ;     //定义标记位

          for(int i=0;i<50;i++){

               if(flag){//如果标志位的内容为true,则表示可以生产

                    this.info .set("上午对应---" ,"am" ) ;     // 设置名称

                   flag = false ;

              } else{

                    this.info .set("下午对应---" ,"pm" ) ;     // 设置名称

                   flag = true ;

              }

         }

     }

};

class Consumer implements Runnable{

     private Info info = null ;

     public Consumer(Info info){

          this.info = info ;

     }

     public void run(){

          for(int i=0;i<50;i++){

               this.info .get() ;

         }

     }

};

public class Demo{

     public static void main(String args[]){

         Info info = new Info();     //实例化Info对象

         Producer pro = new Producer(info) ;     //生产者

         Consumer con = new Consumer(info) ;     //消费者

          new Thread(pro).start() ;

          new Thread(con).start() ;

     }

};

 

结果:上午 --> am

下午 --> pm

上午 --> am

下午 --> pm

上午 --> am

下午 --> pm(截取一部分,上午对应am,下午对应pm,数据正确)

 

小结:

1 线程是指程序的运行流程。多线程机制可以同时运行多个程序快,使得程序运行的效率更高

2 run方法时定义在Thread类中的一种fagfa,因此把线程的程序代码编写在run方法汇内所做的覆写的操作

3 Runnable接口中声明了抽象的run方法,因此必须在Runnable接口的类中明确定义run方法

4Thread类中的sleep方法可以用来控制线程的休眠状态,休眠的时间要看sleep中的参数而定

5 要强制运行某一线程,可以使用join方法

6 当多个线程对象操纵同一共享资源时,要使用 synchronized 关键字来进行资源的同步处理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值