JAVA中线程、锁使用及其基本方法

高并发 - 3.锁及其原理 Java内置锁是一个互斥锁,这就意味着最多只有一个线程能够获得该锁,当线程B尝试去获得线程A持有的内置锁时,线程B必须等待或者阻塞,直到线程A释放这个锁,如果线程A不释放这个锁,那么线程B永远等待下去 Java中每个对象都可以用作锁,这些锁称为内置锁。线程进入同步代码块或方法时会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁保护的同步代码块或方法 阅读详情

目录


概述

进程:是一个正在执行中的程序,每一个进程的执行都有一个执行顺序,该执行顺序是一个控制单元。是线程的容器。资源调度、分配和管理的最小单位。
线程:是进程中的一个独立的控制单元、运行基本单位(CPU调度的最小单位),线程控制着进程的执行。


线程系列

每一个进程中至少有一个线程,在java中主(main)线程就是一条线程。Java程序每次运行不止有一个main线程,还有如垃圾回收机制的线程

如何实现线程?

  • 根据JavaAPI中所写,有Thread类。

public class Thread extends Object implements Runnable

  • 创建一个新的执行线程有两种方法。

    一、将一个类声明为Thread的子类,这个子类应该重写run类的方法Thread
    二、创建一个线程是声明实现类Runnable接口。那个类然后实现了run方法。然后可以分配类的实例,在创建Thread时作为参数传递,并启动。

//方法一
class PrimeThread extends Thread{
    public void run(){
        //需要线程执行的代码
    }
}
public static void main(String[] args){
    PrimeThread p = new PrimeTherad();
    p.start();
}
//方法二
class PrimeRun implements Runnable{
    public void run(){
        //需要线程执行的代码
    }
}
public static void main(String[] args){
    PrimeThread p = new PrimeTherad();
    Thread t = new Thread(p);
    t.start();
    //简写 new Thread(new PrimeThread()).start();
}
  • 为什么要覆盖run()方法?
    Thread类用于描述线程。该类就定义了一个功能,用于存储要线程运行的代码,该存储功能就是run()方法。可以看出main()方法是存放主线程代码的位置。

线程的使用

  • 随机性:
    谁抢到cpu谁执行(多核除外),至于执行多长时间是cpu说了算。一般不会刻意的执行完一条线程再执行另一条。

  • 生命周期:
    线程流程图

  • 两种方法使用的区别
    在上述自定义线程中我们可以知道一共有两种方法可以实现多线程。
    那么这两种有什么区别呢?
    一、避免单继承的局限性:
    二、代码存放的位置不同:
    继承Thread,线程代码存放在Thread子类run方法中。
    实现Runnable,线程代码存放在接口的子类的run方法中。
    因为Runnable只有一个抽象方法run()。

多线程的安全问题

  • 问题原因
    当多条语句操作同一个线程共享数据时,一个线程对多条语句只执行一部分,还没有执行完,另一个线程参与进行执行,导致共享数据的错误。

  • 解决办法
    对多条操作共享数据的语句,只能让一个线程执行完在执行过程中不可以参与执行。Java提供了同步代码块——synchronized,实现了其原子性。

所以推荐使用Runnable接口实现多线程

停止线程

一般来说开启多线程运行的运行代码是循环结构,所以只要控制循环,就可以让run方法运行结束,线程就结束了,这种是最好的。

  • interrupt()

public void interrupt()
中断这个线程。

一般使用方法:用其他线程去打断处于阻塞(冻结)状态的线程,强制使其恢复带运行状态。这时该被恢复的线程会抛出InterruptException异常,我们就可以在这个catch里面进行代码操作。

  • setDaemon()

public final void setDaemon(boolean on)
将此线程标记为daemon线程或用户线程。当运行的唯一线程都是守护进程线程时,Java虚拟机将退出。
线程启动前必须调用此方法。

当线程开启守护线程后与普通线程共用CPU资源,在这些过程中是没有区别的。
当所有非守护线程结束后,JVM退出,守护线程会自动结束。

  • join()

public final void join() throws InterruptedException
等待这个线程死亡。

当前线程调用这个方法时,表该线程需要当前CPU的执行权(抢夺性的),拥有者CPU执行权的线程会释放执行权。一般用于临时加入线程。

  • yield

public static void yield()对调度程序的一个暗示,即当前线程愿意分享当前使用的CPU。 调度程序可以自由地忽略这个提示。
以改善否则会过度利用CPU的线程之间的相对进度。 其使用应与详细的分析和基准相结合,以确保其具有预期的效果。

临时释放,稍微缓解线程的执行频率以达到线程能平均占有CPU的效果。

其他常用方法

  • setPriority

public final void setPriority(int newPriority)更改此线程的优先级。

默认的优先级是5,(1-10),优先级越高执行频率越高,哪怕是10也不存在一直完全占有CPU。
默认参数(MIN_PRIORITY,NORM_PRIORITY,MAX_PRIORITY)

  • toString

public String toString() 返回此线程的字符串表示,包括线程的名称,优先级和线程组。

Thread 类中覆盖了Object 中toString 方法建立了特有的字符串表现形式。

  • getName

public final String getName()返回此线程的名称。

使用线程的快速方式

//一
new Thread(){
    public void run(){
        //线程执行代码
    }
}.start();
//二
Thread t = new Runnable(){
    public void run(){
        //线程执行代码
    }
}
new Thread(t).start();

锁系列

锁是用于通过多个线程控制对共享资源的访问的工具。通常,锁提供对共享资源的独占访问:一次只能有一个线程可以获取锁,并且对共享资源的所有访问都要求首先获取锁。

如何实现锁?

  • 特点:
    对象如同锁,持有锁的线程可以在同步中执行。需要用一个对象锁。 弊端:多个线程需要判断锁,较销毁资源。

  • 同步前提:
    1、两个或者两个线程以上的时候。
    2、多个线程需要使用同一个锁。

  • 同步表现形式
    一、同步代码块。 二、同步函数。

synchronized(对象){
    //需要被同步的代码
}

public synchronized void Demo(){
    //需要被同步的代码
}
  • 是哪一个锁?
    实现一,锁是括号中传入的对象。
    实现二,锁是当前的类是this。
    因为函数需要被对象调用,那么函数都有一个所属引用。就是this。

  • 静态函数是哪一个锁?

public static synchronized void Demo(){
    //需要被同步的代码
}

静态进内存时,没有本类对象,所以没有this。 是由类调用的,所以是该类对应的字节码文件对象 —— 类名.class

死锁

  • 死锁的形成
    当两个或两个以上的进程或线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。
synchronized(对象1){
//拥有对象1锁的线程执行到着的时候就会去获取对象2的锁,
    synchronized(对象2){
        //需要被同步的代码
    }
}

synchronized(对象2){
//拥有对象2锁的线程执行到着的时候就会去获取对象1的锁,
    synchronized(对象1){
        //需要被同步的代码
    }
}

线程间的通讯

在多线程的程序中线程之间的通讯是非常重要的

Object-wait and notify and notifyAll

该方法只能由作为该对象的监听器的所有者的线程调用。

  • wait()
 public final void wait()
            throws InterruptedException

导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。
当前的线程必须拥有该对象的监听器。 该线程释放此监听器的所有权,并等待另 一个线程通知等待该对象监听器的线程通过调用notify方法或notifyAll方法 。
然后线程等待,直到它可以重新获得监听器的所有权并恢复执行。

  • 注意点
    一、我们可以知道wait() notify() notifyAll() 只能用于同步中。
    二、wait() 是让持有当前锁上的线程等待并交出锁监听器。
    三、只能让另一个线程执行notify()或notifyAll()才能唤醒wait()中的线程。
    四、在执行的时候可以用 锁对象.wait() 的方式执行。
    五、一个锁就对应了一个Object。

  • wait() 机制
    在同步中,当一个线程执行 锁对象.wait() 的时候 这个线程将会回到线程池中按顺序进行等待唤醒。意思就是说当有第一个线程被 wait() 的时候它回到线程池中排序为第一号,第二个被 wait() 回到线程池就是第二号,所以当另一个线程执行notify的时候首先被唤醒的就是第一号。

  • 为什么定义在Object类中?
    因为这些方法在操作同步中线程时,都必须标识它们所操作的持有锁,只有同一个锁上的被等待的线程,可以被同一个 notify() 唤醒,不可以对不同锁中的线程进行唤醒。

  • 弊端
    在多线程中哪个线程获得cpu是具有随机性的,所以如果我们要处理多线程之间的等待和唤醒的时候,就可能会遇到问题造成所有的线程都进行wait()状态。

  • notify() 和 notifyAll() 区别
    因为存在上述的弊端,所以就出现了notifyAll()它可以唤醒同一个锁上被 wait() 的所有线程。

Lock

Lock实现提供比使用synchronized方法和语句可以获得的更广泛的锁定操作。 它们允许更灵活的结构化,可能具有完全不同的属性,并且可以支持多个相关联的对象Condition(特点:可实现一个Lock对应多Condition) 。

  • Condition
    Condition因素将Object监听器方法(wait,notify和notifyAll )放入到不同的对象,以使每个对象具有多个等待集合的效果,通过将它们与任意的Lock实现结合使用。 Lock替换synchronized方法和语句的使用, Condition取代了Object监听器方法的使用。

一个Condition实例本质上绑定到一个锁。 要获得特定Condition实例的Condition实例,请使用其newCondition()方法。

  • Condition基本使用
    void await() 导致当前线程等到发信号或 interrupted 。
    signal() 唤醒一个等待线程。
    signalAll() 唤醒所有等待线程。

  • Lock基本使用
    void lock() 获得锁。
    Condition newCondition() 返回一个新Condition绑定到该实例Lock实例。
    void unlock() 释放锁。

  • 注意点
    当在不同范围内发生锁定和解锁时,必须注意确保在锁定时执行的所有代码由try-finally或try-catch保护,以确保在必要时释放锁定。

  • 用它特有的性质实现生产者-消费者模式

import java.util.concurrent.locks.*;
class ProductConsumerDemo{
    public static void main(String[] args){
        Rescure res = new Rescure();
        new Thread(new Producer(res)).start();
        new Thread(new Consumer(res)).start();
        new Thread(new Producer(res)).start();
        new Thread(new Consumer(res)).start();
    }
}

class Rescure{
    private int count = 1;
    private String name;
    private boolean flag = false;

    private Lock lock = new ReentrantLock();
    private Condition condition_pro = lock.newCondition();
    private Condition condition_con = lock.newCondition();

    public void set(String name)throws InterruptedException{
        lock.lock();
        try{
            while(flag)
                condition_pro.await();
            this.name = name+"---"+count++ ;
            String threadName=Thread.currentThread().getName();
            System.out.println(threadName+"生产"+this.name);
            flag = true;
            condition_con.signal();
        }
        finally{
            lock.unlock();
        }
    }

    public void out()throws InterruptedException{
        lock.lock();
        try{
            while(!flag)
                    condition_con.await();
            String threadName=Thread.currentThread().getName();
            System.out.println(threadName+"消费----"+this.name);
            flag = false;
            condition_pro.signal();
        }
        finally{
            lock.unlock();
        }
    }
}

class Producer implements Runnable
{
    private Rescure res;
    Producer(Rescure res){
        this.res = res;
    }
    public void run(){
        while(true){
            try{
                res.set("商品");
            }catch(Exception e){}
        }
    }
}

class Consumer implements Runnable
{
    private Rescure res;
    Consumer(Rescure res){
        this.res = res;
    }
    public void run(){
        while(true){
            try{
                res.out();
            }catch(Exception e){}
        }
    }
}

[STM32]HAL STM32F103 软件I2C读写MPU6050(附DMP库移植) 本文介绍了如何在STM32F103C8T6上通过I2C协议与MPU6050传感器通信并实现DMP功能。首先,使用STM32CubeMX配置项目,设置时钟和I2C接口。然后,编写软件I2C协议的读写函数与MPU6050交互。接着,移植DMP库并进行必要修改,获取加速度计和陀螺仪数据,并将其转换为欧拉角显示在OLED上。最后,利用Keil的逻辑分析仪监测I2C时序。 阅读详情

相关推荐

CST实战:变容二极管电容曲线提取全流程(附S参数设置技巧)

本文详细介绍了在CST Studio Suite中提取变容二极管电容-电压(C-V)曲线的完整实战流程。重点解析了S参数仿真的核心原理、DCFEED模块的正确配置、参数扫描的设置技巧,并探讨了集成SPICE模型进行精确仿真的方法,帮助射频工程师高效、准确地获取器件关键特性。

weixin_29237635的博客 529

Java多线程及锁的简单介绍

Java多线程及锁简介

xx的博客 648

如何在OBS中添加实时时间戳:Lua脚本配置教程(附效果展示)

本文详细介绍了如何在OBS中通过Lua脚本配置实时时间戳功能,包括环境准备、脚本获取、安装配置及高级定制。适用于直播和视频录制场景,提供精准回溯和风格自定义,支持多平台适配和性能优化,是专业制作的必备技巧。

day7的博客 1040

【线程系列之二】线程锁之互斥锁介绍

公平的互斥量会按照线程请求锁的顺序来授予锁,从而避免了饥饿现象(即某个线程长时间得不到锁的情况)。:互斥量保证在任何时候,只有一个线程可以持有锁并访问受保护的资源。:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。死锁是指在执行过程中,两个或两个以上的进程或线程由于竞争资源或彼此通信而阻塞,导致无法继续执行的情况。

qq_40604302的博客 3236

Opencv2.4.9源码分析——HoughCircles

图形可以用一些参数进行表示,标准霍夫变换的原理就是把图像空间转换成参数空间(即霍夫空间),例如霍夫变换的直线检测就是在距离-角度空间内进行检测。圆可以表示成: (x-a)2+(y-b)2=r2                   (1) 其中a和b表示圆心坐标,r表示圆半径,因此霍夫变换的圆检测就是在这三个参数组成的三维空间内进行检测。 原则上,霍夫变换可以检测任何形状。但复杂的形状需要的

赵春江的专栏 3万+

[SDIO] SD card 初始化及常用命令解析(附波形,uboot代码)

目录 初始化 1.cmd 0 2.cmd8 3.cmd55 4.acmd41 5.cmd2 6.cmd3 7.cmd9 8.cmd13 9.cmd7 10.ACMD51 11.CMD6 12.CMD16 13.CMD17 14.CMD18 15.CMD12 tuning CMD19 DW_SDHCI的tuning流程 初始化 1.cmd 0 /* Reset the Card */ err = mmc_go_idle(mmc...

Lenz_s_law的开发记录本 2万+

(一)线程安全问题-线程锁(synchronized的使用)

(一)线程安全问题诱因 存在有共享数据 存在有多个线程访问这些共享数据 解决方法:同一时刻共享数据只能由一个线程访问,其他线程要等到该线程处理完共享数据后才能对该线程进行操作 (二)线程锁-synchronized 线程锁的两个特性 互斥性:同一时间只能有一个对象持有线程锁,通过这种特性实现多线程的协调机制。同一时间只有一个线程对需要同步的代码块进行访问,也成为原子性 可见性:必须确保在锁释放之前,其对于共享变量的修改对下一个获得该锁的线程是可见的,否则另一个线程可能是在本地缓存的某个副本上进行,

roothahh的博客 8246

OpenIddict实战:5步搞定.NET Core应用的OIDC单点登录集成

本文详细介绍了如何使用OpenIddict在.NET Core应用中快速实现OIDC单点登录集成。通过五个关键步骤,包括环境准备、数据库集成、客户端注册、令牌配置和多应用SSO集成,帮助开发者高效构建安全的企业级单点登录解决方案。

lambda的博客 726

线程并发——锁(超简单)

什么是互斥锁呢,我给大家举个例子,我们可以想象成是车站的座位,然后把线程比喻成一个人,你进车站候车的时候,你就要先找到没有人的座位,然后坐下去(表示你正在使用),这样其他的人(其他的线程)就无法再使用这个座位了,如果想要使用该座位就需要你站起来,别人才可以使用。并发:同时发生在生活中,可能会有多个执行单元,同时访问同一个资源。比如座位。使用锁(互斥锁)来保护资源互斥锁:一个时刻值允许一个执行单元访问共享资源1.定义并初始化一把锁2.访问共享资源前。

Linux驱动开发工程师,熟悉Linux/Android底层驱动、TP、显示、IIC、网络等通用外设调试适配,Linux上层应用开发。常用平台瑞芯微、全志、恩智浦等。 1912

《拉依达的嵌入式\驱动面试宝典》—Linux篇(八)_Linux驱动编程

《拉依达的嵌入式\驱动面试宝典》 整合了所有我认为可能遇到的技术面试问题。所有问题及其答案均是我个人学习后查阅资料总结,每个回答都做了仔细的分析,在嵌入式及其驱动面试相关问题解析做到全网独一无二。学习或者转行到嵌入式、驱动开发领域学习的不二之选

拉依达不拉跨的博客 319

设计四翼无人机(Quadcopter)的自主降落控制算法

为四翼无人机建立动力学模型,包括其姿态(Pitch, Roll, Yaw)和位置(X, Y, Z)的变化。可以使用Aerospace Blockset中的预制模块,或者根据具体需求构建自定义模型。示例:简化动力学模型利用块模拟四翼无人机的基本行为,确保模型能够反映电机输出如何影响姿态和位置变化。

amy_mhd的博客 242

Java中线程基础-线程间协作-调用yield() 、sleep()、wait()、notify()等方法对锁有何影响?

调用yield() 、sleep()、wait()、notify()等方法对锁有何影响? 线程在执行yield()以后,持有的锁是不释放的 sleep()方法被调用以后,持有的锁是不释放的 调动方法之前,必须要持有锁。调用了wait()方法以后,锁就会被释放,当wait方法返回的时候,线程会重新持有锁 调动方法之前,必须要持有锁,调用notifyAll()方法本身不会释放锁的 ...

Marlon康 400

推荐系统[八]算法实践总结V3:重排在快手短视频推荐系统中的应用and手淘信息流多兴趣多目标重排技术

快手推荐系统包括了传统的召回、粗排、精排、Learning To Rank 的多目标排序、多目标预估等技术环节。而在这些模块之后的技术环节就属于重排序,主要包括手机端和服务端两部分。服务端通过传统服务器部署重排服务,包括序列重排、多源内容混排、多样性模块。端上部分包括端上重排模型和端上重排策略两部分。重排技术是快手十分重要的技术环节,它的发展速度远快于其他排序环节,属于较新的技术范畴。整个序列的价值并非单 item 效果的累计,如何使得序列价值最大化;

丨汀、的博客 1061

测试线程sleep不让出锁

一直听说线程sleep不让出锁,现做个实验,代码如下 先写一个类,方法上都同步。 package test.thread.impl; public class ThreadSleep { public synchronized void method1() throws InterruptedException { System.out.println("this ...

xby7437的博客 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

java线程的使用方法_Java中线程的基本方法使用技巧

java中线程的基本方法的熟练使用是精通多线程编程的必经之路,线程相关的基本方法有wait,notify,notifyAll,sleep,join,yield等,本文浅要的介绍一下它们的使用方式。线程的状态图java将操作系统中的就绪和运行两种状态统称为可运行状态,java中线程的状态可以认为有以上六种。wait调用该方法的线程进入WAITING状态,只有等待另外线程的通知或被中断才会返回,需要注...

weixin_31225063的博客 336

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

java 类锁和对象锁

java 静态锁和对象锁 对象锁 java中要实现线程同步, 同一个类中使用 synchronized 关键字在方法上或者代码块中 默认表示使用当前对象的锁 多线程访问时候会进行抢锁,释放锁,通对象的方法执行分先后顺序 以下方法 lock1 lock2 lock3 表示相同的对象锁 lock4 表示的是 成员变量 object 的锁 输出的时候 lock1 lock2 lock3 之中一个和 l......

. 2102

android 蓝牙通讯demo

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

Java中线程Thread以及加锁synchronized

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Ma...

山四的博客 584

同步方法调用另一个同步方法的锁

2 下列的叙述正确的是() public class Test2 { public static synchronized void main(String[] args) { Thread t = new Thread(){ public void run() { Sogou();

JJ_nan的博客 1921

Java中线程同步的常见方法、代码示例及对比表格

Java中线程同步的常见方法、代码示例及对比表格

爱的叹息的专栏 398

java同步锁(synchronized)锁方法还是锁类??

首先引入gitHub上面一个解释 一.原理分析 1. 同步一个代码块 public void func() { synchronized (this) { // ... } } 它只作用于同一个对象,如果调用两个对象上的同步代码块,就不会进行同步。 2. 同步一个方法 public synchronized void func () { // ... } ...

weixin_43186523的博客 1236

Java中线程的状态

在Java当中把对线程的状态分得比原生操作系统更加细致,在。线程处于运行状态或者处在就绪队列,等待CPU资源。发现,当线程调用上面3个方法时,会进入。结束状态,表示线程已经执行完毕。这个状态表示线程正在等待锁资源。类内部,定义了一个枚举类型。线程刚创建出来,还未执行。当线程进入有限等待时进入。代码块,而后来的线程。.........

qq_57735833的博客 309

java高并发18——饥饿线程与公平锁

If a thread is not granted CPU time because other threads grab it all, it is called “starvation”. The thread is “starved to death” because other threads are allowed the CPU time instead of it. The sol...

路人甲的路人乙的专栏 947

JAVA中的锁——Synchronized

线程会出现的问题:同步 与 互斥 什么是同步? 什么是互斥? Synchronized 可以作用于哪里?实现的原理?性能优化有什么? 1.首先来说说什么是同步与互斥? 同步:线程间的通信(线程合作) 互斥:多线程并发时,某一时刻只能有一个线程访问共享资源 2.Synchronized同步处理可以作用于哪里:(1)同步方法 (2)同步代码块 (1)同步代码块: 锁的对象是 ...

qq_43221635的博客 243

java 两套锁_Java性能测试中两种锁的实现

在使用Java进行性能测试过程中,经常会遇到线程同步代码锁的使用,同步内容的对象、方法、代码块。同步是使所有并发线程在执行中保持同步的过程。同步避免了由于共享内存视图不一致而导致的内存一致性错误。当方法被声明为同步时,该线程持有监视器或锁定对象为这个方法的对象。如果另一个线程正在执行同步方法,则该线程将被阻塞,直到该线程释放这个锁。可以通过synchronized在类中的已定义方法或块上使用。对象...

weixin_42213784的博客 264

Java基础之利用锁实现线程同步的几种方法

这要从线程的运行过程说起,线程并非是让一个代码块运行完再让另一个代码块运行,而是无论一处代码是否执行完,只要过了一段时间就让另一个代码块执行。因此有时在对money进行一个操作后,另一个得到的数据还是之前的数据,从而导致差错。是利用synchronized(监视器(锁)){ 需要同步的代码块...}语句来手动加锁,在小括号中的就是锁的本体,要求必须唯一且对所有线程适用,只要满足这个条件的任意对象都能作为锁,因为这是一个参照物,只有与一个不变的东西对比才能知道数据有没有被改变,可以类比于物理中。

Zhuanxin_shenyou的博客 568

【Java高级】JUC之线程八锁案例分析

class Phone{ public static synchronized void sendEmail()throws Exception{ TimeUnit.SECONDS.sleep(4); System.out.println("****sendEmail"); } public synchronized void sendSMS...

阿杰 541
上一篇: VirtualBox+openwrt+ubuntu16.04 实现ssh
下一篇: Java中String、StringBuffer及包装类
虾米馅煎包
博客等级 码龄10年 2粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值