包装类、多线程的基本使用

这篇具有很好参考价值的文章主要介绍了包装类、多线程的基本使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

包装类

1.基本数据类型对应的引用数据类型(包装类)

1.概述:所谓的包装类就是基本类型对应的类(引用类型),我们需要将基本类型转成包装类,从而让基本类型具有类的特性(说白了,就是将基本类型的数据转成包装类,就可以使用包装类中的方法来操作此数据)
    
2.为啥要学包装类:
  a.将来有一些特定操作,调用方法需要传递包装类
    比如:ArrayList集合,add(Object obj),我们只能传递Object的子类对象,此时如果我们想传递一些基本类型的数据,Object作为一个引用类型不能直接接受基本类型,所以我们需要先将基本类型转成包装类传递到Object3.将来我们需要让基本类型和包装类互相转换,为啥:
  a.基本类型为啥转成包装类:
    调用某个方法,方法参数传递Object类型,ArrayList集合,add(Object obj),我们只能传递Object的子类对象,此时如果我们想传递一些基本类型的数据,Object作为一个引用类型不能直接接受基本类型,所以我们需要先将基本类型转成包装类传递到Object中
              
  b.包装类为啥转成基本类型:
    包装类不能直接使用+ - * /做运算,所以需要先将包装类转成基本类型,才能直接使用+ - * /符号
基本类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

2.Inteaer的介绍以及应用

2.1Integer基本使用

1.概述:Integerint的包装类
2.构造:
  a.Integer(String i):i必须是数字格式
  b.Integer(int i)    
public class Exercise {
    public static void main(String[] args) {
        Integer integer = new Integer("10");
        System.out.println("integer = " + integer);
        Integer integer1 = new Integer(100);
        System.out.println("integer1 = " + integer1);

        Boolean aBoolean = new Boolean(true);
        System.out.println("aBoolean = " + aBoolean);
        Boolean aBoolean1 = new Boolean("true");
        System.out.println("aBoolean1 = " + aBoolean1);
        Boolean aBoolean2 = new Boolean("True");
        System.out.println("aBoolean2 = " + aBoolean2);
    }
}
//输出
integer = 10
integer1 = 100
aBoolean = true
aBoolean1 = true
aBoolean2 = true
Boolean aBoolean = new Boolean(true);

Boolean包装类中 , 底层调用了parseBoolean(String s) , 在parseBoolean中调用了equals.IgnoreCase(s) , 忽略了大小写

public static boolean parseBoolean(String s) {
    return "true".equalsIgnoreCase(s);
}

2.2装箱and拆箱

1.装箱:
  将基本类型变成包装类
      
2.方法:
  static Integer valueOf(int i)  
  static Integer valueOf(String s) -> s需要是数字格式
1.拆箱:将包装类转成基本类型
2.方法:
  int intValue()  
public class Exercise03 {
    public static void main(String[] args) {
        //装箱
        Integer integer = Integer.valueOf(10);
        System.out.println("integer = " + integer);
        Integer integer1 = Integer.valueOf("15");
        System.out.println("integer1 = " + integer1);
        //拆箱
        int value = integer.intValue();
        System.out.println("value = " + value);
        int value1 = integer1.intValue();
        System.out.println("value1 = " + value1);
    }
}

2.3自动拆箱装箱

在操作的过程中,基本类型和包装类之间可以自动转换

public class Demo04Integer {
    public static void main(String[] args) {
        Integer i = 10;
        i+=1;
        System.out.println(i);
    }
}

反编译后如下图:

1694497269393

笔试题:

public class Demo05Integer {
public static void main(String[] args) {
    Integer i1 = 100;
    Integer i2 = 100;
    System.out.println(i1==i2);//true

    Integer i3 = 127;
    Integer i4 = 127;
    System.out.println(i3==i4);//true

    Integer i5 = 128;
    Integer i6 = 128;
    System.out.println(i5==i6);//false
}
}
包装类 缓存对象
Byte -128-127
Short -128-127
Integer -128-127
Long -128-127
Float 没有
Double 没有
Character 0-127
Boolean true和false
@IntrinsicCandidate
public static Integer valueOf(int i) {
   if (i >= IntegerCache.low && i <= IntegerCache.high)
       return IntegerCache.cache[i + (-IntegerCache.low)];
   return new Integer(i);
}

可以发现当数值超过了128就会开辟一个新空间 , 即new Integer(i)

此为享元设计模式

3.基本类型与String转换

3.1 基本类型往String转

1.方式1:
  +
2.方式2:String中的静态方法
  static String valueOf(int i)  
public class String_transform {
    public static void main(String[] args) {
        //基本数据类型转包装类
        //方式1: static String valueOf(int a)
        String s = String.valueOf(10);
        System.out.println(s+1);

        //方式2:+""
        int i  = 10;
        String s1 = i+"";
        System.out.println(s1+1);

    }
}

3.2 String转成基本数据类型

每一个包装类中都有一个parseXXX的方法
位置 方法 说明
Byte static byte parseByte(String s) 将字符串转成byte
Short static short parseShort(String s) 将字符串转成short
Integer static int parseInt(String s) 将字符串转成int
Long static long parseLong(String s) 将字符串转成long
Float static float parseFloat(String s) 将字符串转成float
Double static double parseDouble(String s) 将字符串转成double
Boolean static boolean parseBoolean(String s) 将字符串转成boolean
public class String_transform {
    public static void main(String[] args) {
        //基本数据类型转包装类
        //方式1: static String valueOf(int a)
        String s = String.valueOf(10);
        System.out.println(s+1);

        //方式2:+""
        int i  = 10;
        String s1 = i+"";
        System.out.println(s1+1);


        //将String转为基本数据类型
        int i1 = Integer.parseInt("101");
        System.out.println("i1+1 = " + i1+1);
        double parseDouble = Double.parseDouble("10.2");
        System.out.println("parseDouble+1 = " + parseDouble + 1);
    }
}

将来开发,我们定义javabean的时候,需要将基本类型的字段(成员变量)定义成包装类类型的

1.将来我们的javabean都是和表对应的
2.针对下面的Student,创建出来的表
id   -> 一般作为表的主键使用,而且主键会自增
name
age

如果主键为自增,我们添加数据时sql语句可以这么写:
insert into student (id,name,age) values (NULL,'柳岩',36);
我们可以用NULL占位(主键自增的列)
    
而我们将来需要将javabean对象中的数据添加到sql语句中,从而保存到数据库中
    
包装类型的属性默认值为NULL,所以到时候我们将javabean对象中的数据放到数据库中时,我们不需要单独为id属性赋值
    
如果不给javabean中的id赋值: Student s = new Student(null,"哈哈",36)
此时我们将javabean中的属性值获取出来放到sql中,正好是: 
insert into student (id,name,age) values (NULL,'哈哈',36);
public class User {
   private Integer uid;
   private String name;
   private Integer age;

   public User(Integer uid, String name, Integer age) {
       this.uid = uid;
       this.name = name;
       this.age = age;
   }

   public User() {
   }

   public Integer getUid() {
       return uid;
   }

   public void setUid(Integer uid) {
       this.uid = uid;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public Integer getAge() {
       return age;
   }

   public void setAge(Integer age) {
       this.age = age;
   }

   @Override
   public String toString() {
       return "User{" +
               "uid=" + uid +
               ", name='" + name + '\'' +
               ", age=" + age +
               '}';
   }
}

多线程

1.多线程_线程和进程

1694511947394

进程(Processor) : 程序的一次执行。由操作系统创建并分配资源,执行一个单独的任务。 进程是系统进行资源分配和调度的独立单位,每个进程都有自己的内存空间和系统资源。进程内所有线程共享堆存储空间,保存程序中定义的对象和常量池。

线程作用 : 负责当前进程中程序的运行 , 一个进程中至少有一个线程 . 一个进程中是可以有多个线程的,这样的应用程序就称之为多线程程序 . 线程是进程内的执行单元,不分配单独的资源,执行一个单独的子任务。线程是进程内调度和分派的基本单位,共享进程资源。每个线程有自己的独立的栈存储空间,保存线程执行的方法以及基本类型的数据。 运行的 Java 程序内含至少一个主线程 main ,用户可以在 Java 程序中自定义并调用多个线程。 JVM 垃圾回收线程也是一个独立的线程。

并发:同一个时刻多个线程同时操作了同一个数据 , 多个任务交替使用 CPU 核心工作,以提高 CPU 利用率。

并行:同一个时刻多个线程同时执行不同的程序 , 多个CPU核心同时工作,处理不同的任务。

2.CPU调度

1.分时调度:指的是让所有的线程轮流获取CPU使用权,并且平均分配每个线程占用的cpu的时间片
2.抢占式调度:多个线程轮流抢占CPU使用权,哪个线程先抢到,哪个线程先执行,一般都是优先级高的抢到CPU使用权的概率大,我们java程序都是抢占式调度

线程的运行状态 : 线程除创建状态 New 和结束状态 Terminate 外,主要有以下几种运行状态:

NEW(新建) : 线程刚被创建,但是并未启动。还没调用start方法。

运行 : (Running) CPU 正在执行线程。

就绪 : (Runnable) 线程一切就绪,等待 CPU 执行。

运行/就绪状态 统称为可运行状态 Runnable。 Java 程序中,线程在 运行/就绪状态 之间的切换由 JVM 自动调度,开发者无法获知。线程之间的调度采用分优先级多队列时间片轮转算法。进程在执行完 CPU 时间片切换到就绪状态之前会先保存自己的状态,下次进入运行状态时再重新加载。

阻塞 : (Blocked) 线程因缺少其他资源,比如请求资源被上锁而暂停执行。在获得资源后进入就绪状态。 一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。

等待 : (Waitting) 线程接受了等待指令,释放资源暂停执行。在超时/接受唤醒指令后进入就绪状态。 同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。

Terminated(被终止) : 因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。或者调用过时方法stop()

3.主线程介绍

在CPU和内存之间专门为main开辟的通道叫做主线程

主线程专门运行main方法的

1694513606433

创建线程的方式(重点)

1.第一种方式_extends Thread

步骤 :

​ ①定义类 , 继承Thread类(Thread是一个线程类)

​ ②重写Thread中的run方法 , 设置线程任务(自定义的线程需要干什么 , 将业务写进run())

​ ③创建自定义线程类对象

​ ④调用Thread中的start方法(使线程开始执行 ; Java虚拟机会调用线程中的 run 方法)

public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("我是MyThread....");
        }
    }
}
public class Test01 {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();	//开启线程 , jvm自动调用重写的run方法

        for (int i = 0; i < 3; i++) {
            System.out.println("我是主线程...");
        }
    }
}

2.多线程在内存中的运行原理

当有多个线程开启时 , 进程会为每个线程独自开启新线程的栈空间

注意 : 同一个线程对象 , 不可以连续调用多个start方法

如果需要开启多个线程 , 需要重新new

3.Thread类中的方法

1.void start() 开启线程,jvm会自动执行run方法
2.String getName() 获取线程名字
3.static Thread currentThread()  -> 获取的是当前正在执行的线程对象,此方法在哪个线程中用,获取的就是哪个线程对象 
4.void setName(String name) -> 给线程设置名字
5.static void sleep(long time)->线程睡眠,传递毫秒值,时间超时,线程自动醒来,自动继续执行   
public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            Thread.sleep(1000l);
            System.out.println(getName()+"线程正在执行....");   
            //getName()  获取线程名字   因为继承了Thread,可以直接调用
        }
    }
}
public class Test01 {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();		//开启线程 , jvm自动调用重写的run方法
        myThread.setName("haha");	//修改线程名字
        for (int i = 0; i < 3; i++) {
            Thread.sleep(1000l);	//线程睡眠1秒
            System.out.println(Thread.currentThread().getName()+"线程正在执行..."); //static Thread currentThread()   获取的是当前正在执行的线程对象
        }
    }
}
//输出
main线程正在执行...
haha线程正在执行....
main线程正在执行...
haha线程正在执行....
main线程正在执行...
haha线程正在执行....

4.第二种方式_实现Runnable接口

步骤 :

​ ①定义一个类 , 实现Runnable接口

​ ②重写run方法 , 设置线程任务

​ ③创建自定义的线程类对象

​ ④利用Thread中的构造方法 : Thread(Runnable target) , 创建实现类对象 , 放到Thread中

​ ⑤调用start方法 , 启动线程

public class MyThread_implements implements Runnable{
    @Override
    public void run() {
        try {
            Thread.sleep(100L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName()+"线程正在执行....");
        }
    }
}
public class Test02 {
    public static void main(String[] args) throws InterruptedException {
        MyThread_implements myThread_implements = new MyThread_implements();
        Thread thread = new Thread(myThread_implements);
        thread.start();

        for (int i = 0; i < 3; i++) {
            Thread.sleep(100l);
            System.out.println(Thread.currentThread().getName()+"线程正在执行...");
        }
    }
}

问题 : 为什么再run方法中处理异常只能使用try_catch?

因为Thread中的run方法没有抛异常 , 子类重写父类之后也不抛 , 只能try_catch自己解决

5.两种实现多线程的方式区别

继承extends Thread : 由于继承只能单继承 , 如果某个场景它有父类也需要继承 , 就无法继承Thread了 , 所以有局限性

实现implement Runnable : 接口可以多继承多实现 , 解决了继承的局限性 , 一个类继承一个父类的同 时可以实现一个或多个接口 -----> 推荐使用

6.第三种方式_匿名内部类创建多线程

匿名内部类回顾:一种格式代表子类对象或实现类对象

使用:
	new 接口/抽象父类(){
        重写方法
    }.重写的方法();

	接口/抽象类 对象名 = new 接口/抽象父类(){
        重写方法
    }
	对象名.重写的方法();
public class Test03Niming {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 3; i++) {
                    System.out.println(Thread.currentThread().getName()+"匿名线程正在执行...");
                }
            }
        }).start();

        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName()+"主线程正在执行...");
        }
    }
}

线程安全

问 : 什么时候出现线程安全问题 ?

答 : 当多个线程访问同一个资源时 , 可能会出现线程安全问题

1.线程安全问题 —>线程不安全代码

public class MyTicket implements Runnable{
    int ticket = 100;
    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(100L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (ticket>0){
                System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
            }
            ticket--;
        }
    }
}

public class Test01 {
    public static void main(String[] args) {
        MyTicket myTicket = new MyTicket();

        Thread thread1 = new Thread(myTicket,"柳岩");
        Thread thread2 = new Thread(myTicket,"涛哥");
        Thread thread3 = new Thread(myTicket,"金莲");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

原因 : CPU在多个线程中做高速切换

2.解决线程安全问题的第一种方式(使用同步代码块)

格式:
	synchronized(任意对象->锁对象){
        可能出现的线程不安全的代码
    }

执行流程:
	某一个线程抢到锁,进入内部执行,其他线程就抢不到锁了,只能等待,等着执行的线程出了代码块,将锁释放,其他线程才有可能抢到锁对象,去执行
public class Ticket implements Runnable{
    Integer ticket = 50;

    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(100L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            synchronized (this){
                if(ticket > 0){
                    System.out.println(Thread.currentThread().getName()+"抢到了第"+ticket+"张票");
                    ticket--;
                }else{
                    return ;
                }
            }
        }
    }
}
public class Test04 {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        Thread t1 = new Thread(ticket, "张三");
        Thread t2 = new Thread(ticket, "李四");
        Thread t3 = new Thread(ticket, "王五");

        t1.start();
        t2.start();
        t3.start();
    }
}

3.解决线程安全问题的第二种方式:同步方法

3.1.普通同步方法

1.格式:
  public synchronized 返回值类型 方法名(参数){
      方法体
      return 结果
  }

  public 返回值类型 方法名(参数){
      synchronized(this){
          方法体
          return 结果
      }
  }

2.默认锁:this
public class Ticket1 implements Runnable{
    Integer ticket = 50;
    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(100l);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            method();
            if(ticket == 0){
                return;
            }
        }
    }
    /*
    //采用synchronized同步方法
    public synchronized void method(){
        if(ticket > 0){
            System.out.println(Thread.currentThread().getName()+"抢到了第"+ticket+"张票");
            ticket--;
        }
    }*/

    public void method(){
        synchronized (this){
            if(ticket > 0){
                System.out.println(Thread.currentThread().getName()+"抢到了第"+ticket+"张票");
                ticket--;
            }
        }
    }
}
public class Test05 {
    public static void main(String[] args) {
        Ticket1 ticket1 = new Ticket1();
        Thread t1 = new Thread(ticket1, "张三");
        Thread t2 = new Thread(ticket1, "李四");
        Thread t3 = new Thread(ticket1, "王五");
        t1.start();
        t2.start();
        t3.start();
    }
}

3.2.静态同步方法

1.格式:
  public static synchronized 返回值类型 方法名(参数){
      方法体
      return 结果
  }

2.默认锁:
  当前类.class
public class Ticket2 implements Runnable{
    static Integer ticket = 50;
    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(100l);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            method();
            if(ticket == 0){
                return;
            }
        }
    }
    /*
    //采用synchronized同步方法
    public static synchronized void method(){
        if(ticket > 0){
            System.out.println(Thread.currentThread().getName()+"抢到了第"+ticket+"张票");
            ticket--;
        }
    }*/

    public static void method(){
        synchronized (Ticket2.class){
            if(ticket > 0){
                System.out.println(Thread.currentThread().getName()+"抢到了第"+ticket+"张票");
                ticket--;
            }
        }
    }
}
public class Test06 {
    public static void main(String[] args) {
        Ticket2 ticket2 = new Ticket2();
        Thread t1 = new Thread(ticket2, "张三");
        Thread t2 = new Thread(ticket2, "李四");
        Thread t3 = new Thread(ticket2, "王五");

        t1.start();
        t2.start();
        t3.start();
    }
}

死锁

1.死锁介绍(锁嵌套就有可能产生死锁)

​ 指的是两个或者两个以上的线程在执行的过程中,由于竞争同步锁而产生的一种阻塞现象;如果没有外力的作用,他们将无法继续执行下去,这种情况就称之为死锁.

1694519025452
根据上图所示:线程T1正在持有R1,但是T1线程必须再拿到R2,才能继续执行
而线程T2正在持有R2,但是T2线程需要再拿到R1,才能继续执行
此时两个线程处于互相等待的状态,就是死锁,在程序中的死锁将出现在同步代码块的嵌套中

2.死锁的分析

1694519069437

3.代码实现

public class LockA {
    public static LockA lockA = new LockA();
}
public class LockB {
    public static LockB lockB = new LockB();
}
public class DieLock implements Runnable {
    private boolean flag;

    public DieLock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag) {
            synchronized (LockA.lockA) {
                System.out.println("if...lockA");
                synchronized (LockB.lockB) {
                    System.out.println("if...lockB");
                }
            }
        } else {
            synchronized (LockB.lockB) {
                System.out.println("else...lockB");
                synchronized (LockA.lockA) {
                    System.out.println("else...lockA");
                }
            }
        }

    }
}
public class Test01 {
    public static void main(String[] args) {
        DieLock dieLock1 = new DieLock(true);
        DieLock dieLock2 = new DieLock(false);

        new Thread(dieLock1).start();
        new Thread(dieLock2).start();
    }
}

lag = flag;
}

@Override
public void run() {
    if (flag) {
        synchronized (LockA.lockA) {
            System.out.println("if...lockA");
            synchronized (LockB.lockB) {
                System.out.println("if...lockB");
            }
        }
    } else {
        synchronized (LockB.lockB) {
            System.out.println("else...lockB");
            synchronized (LockA.lockA) {
                System.out.println("else...lockA");
            }
        }
    }

}

}文章来源地址https://www.toymoban.com/news/detail-708401.html


~~~java
public class Test01 {
    public static void main(String[] args) {
        DieLock dieLock1 = new DieLock(true);
        DieLock dieLock2 = new DieLock(false);

        new Thread(dieLock1).start();
        new Thread(dieLock2).start();
    }
}

到了这里,关于包装类、多线程的基本使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java之包装类的算法小题的练习

    需求: 键盘录入一些1~10日之间的整数,并添加到集合中。直到集合中所有数据和超过200为止。 代码示例: 需求: 自己实现parseInt方法的效果,将字符串形式的数据转成整数。要求:字符串中只能是数字不能有其他字符最少一位,最多10位 0不能开头 代码示例: 需求: 定义一

    2024年02月09日
    浏览(44)
  • 使用C语言实现多线程DES算法、CPC密码和vigenere算法

    UI.h UI.cpp DES.h  DES.cpp CPC.h CPC.cpp Vigenere.h Vigenere.cpp Common.h Common.cpp Order.h

    2024年02月03日
    浏览(39)
  • Java/Python/Go不同开发语言在进程、线程和协程的设计差异

    在多线程项目开发时,最常用、最常遇到的问题是 1,线程、协程安全 2,线程、协程间的通信和控制 本文主要探讨不同开发语言go、java、python在进程、线程和协程上的设计和开发方式的异同。 进程 进程是 操作系统进行资源分配的基本单位,每个进程都有自己的独立内存空

    2024年01月23日
    浏览(50)
  • 【C语言】多线程基本实现

    在串口助手编程中,-k命令下需要实现等待接收message的同时可以发送键入message。但是,键入message使用的fgets()函数如果得不到键入就会一直等待,无法继续接收message,考虑采用多线程实现有键入则发送,否则一直等待接收message。 计算机的核心是CPU,承担所有的计算任务。

    2024年02月05日
    浏览(35)
  • 【C++】C++11:线程库和包装器

    C++11最后一篇文章 文章目录 前言 一、线程库 二、包装器和绑定 总结 上一篇文章中我们详细讲解了lambda表达式的使用,我们今天所用的线程相关的知识会大量的用到lambda表达式,所以对lambda表达式还模糊不清的可以先将上一篇文章看明白。 一、线程库 在 C++11 之前,涉及到

    2024年02月10日
    浏览(48)
  • Java 多线程的基本概念!

    Java基础合集 数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 其他系列文章导航 文章目录 前言 一、进程和线程 二、使用多线程的目的 三、线程安全 3.1 使用Atomic包下的类: 3.2 使用volatile: 3.3 使用CountDownLatch:  3.4 使用ReentrantLock: 四、死锁解决

    2024年02月03日
    浏览(45)
  • Java 线程池的基本操作

    2024年02月20日
    浏览(39)
  • 第五章 基本引用类型(下)——原始值包装类型、

    5.3 原始值包装类型         为了方便操作原始值,ECMAScript提供了3种特殊的引用类型:Boolean、Number和String。这些类型具有本章介绍的其他引用类型一样的特点,但也具有与各自原始类型对应的特殊行为。每当用到某个原始值的方法或属性时,后台都会创建一个相应原始包

    2024年01月16日
    浏览(44)
  • Maven简介及环境搭建和基本使用(Java开发中的实用工具)

    Maven 是 Apache 软件基金会的一个开源项目,是一个优秀的项目构建工具,它 用来帮助开发者管理项目中的 jar,以及 jar 之间的依赖关系、完成项目的编译、 测试、打包和发布等工作。 pom.xml文件:里面可以配置相关信息,指导maven如何工作 坐标:jar包在仓库中的唯一位置, apache将

    2024年02月02日
    浏览(42)
  • 【C++】 C++11(右值引用,移动语义,bind,包装器,lambda,线程库)

    C++11是C++语言的一次重大更新版本,于2011年发布,它包含了一些非常有用的新特性,为开发人员提供了更好的编程工具和更好的编程体验,使得编写高效、可维护、安全的代码更加容易。 一些C++11的新增特性包括: 强制类型枚举,使得枚举类型的通常行为更加可靠和容易控制

    2024年02月10日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包