前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java多线程

Java多线程

原创
作者头像
用户11010370
发布于 2024-03-08 05:50:35
发布于 2024-03-08 05:50:35
1310
举报

1. java线程实现/创建的方式(主要是两种)

1.继承Thread类

本质是通过实现Runnable接口的一个实例,代表一个线程的实例

代码语言:java
AI代码解释
复制
public class MyThread extends Thread{
    public void run(){
        System.out.println("run()")    
    }
}
MyThread thread = new MyThread();
thread.start();

2.实现Runnable接口

代码语言:java
AI代码解释
复制
public class MyThread extends OtherClass implements Runnable{
    public void run(){
        System.out.println("run()")    
    }
}
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();

2. 线程的生命周期

新建->就绪->运行->阻塞->死亡

1.新建:程序使用new创建线程后,就是新建状态,jvm会为他分配内存,并初始化成员变量的值

2.就绪:线程对象调用start()后,就是就绪状态。java虚拟机会创建方法调用栈和程序计数器,等待调度运行

3.运行:处于就绪状态的线程获得了cpu,执行run()的线程执行体,就是运行状态

补充:线程什么情况会从运行状态变成阻塞状态

  • 使用sleep方法,会主动放弃所占用的系统资源
  • 线程调用一个阻塞式io方法,在方法返回之前都是阻塞状态
  • 线程试图获得一个同步监视器,但更改同步监视器正被其他线程所持有
  • 线程等待某个通知notify
  • 程序调用线程的suspend方法会被线程挂起,容易造成死锁不建议使用

4.阻塞:线程因为某种原因放弃了对cpu的使用权,即让出了cpu timeslice,暂时停止运行,直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice转到运行状态

等待阻塞、同步阻塞、其他阻塞

5.死亡:

  • 正常结束:run()或call()方法执行完成,线程正常结束
  • 异常结束:线程抛出一个未捕获的Exception或Error
  • 调用stop:直接调用该线程的stop()方法来结束线程,容易导致死锁

3. 终止线程的方式

  1. 正常运行结束
  2. 使用退出标志退出线程(volatile关键字的目的是让exit同步)
  3. interrupt方法结束线程
  4. stop方法终止线程(线程不安全)

4. sleep和wait区别

  1. sleep()是静态的Thread类的方法,wait()是Object类中的方法
  2. sleep()方法导致线程暂停执行指定的时间,让出cpu给其他线程,但是他的监控状态依旧保持,到了指定时间又会自动恢复运行状态,在调用的过程中,线程不会释放对象锁
  3. 调用wait()方法过程中,线程会放弃对象锁,进入等待对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态

5.start和run区别

  1. start()用来启动线程,不需要等待run()方法体代码执行完就可以继续执行下面的代码。
  2. run()称为线程体。包含执行线程的内容,线程进入到了运行状态,开始运行run中的代码,运行结束后,线程才会终止,然后cpu再调度其他线程

6. 乐观锁、悲观锁和自旋锁

6.1 乐观锁(AtomicInteger)

乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新(说明没有人去修改过数据,所以更新),不一样算提交失败),如果失败则要重复读-比较-写的操作。java 中的乐观锁基本都是通过 CAS 操作实现的,CAS 是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。

6.2 悲观锁 ( synchronize lock)

悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会 block 直到拿到锁。java中的悲观锁就是Synchronized,AQS框架下的锁则是先尝试cas乐观锁去获取锁,获取不到,才会转换为悲观锁,如 RetreenLock。

6.3 自旋锁

如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。

出现的原因:如果存在大量互斥同步代码,当出现高并发的时候,系统内核态就需要不断地去挂起线程和恢复线程,频繁的操作就会对系统的并发性能有一定的影响

java 非公平自旋锁

代码语言:java
AI代码解释
复制
/**
 * 锁的持有者
 */
private AtomicReference<Thread> owner = new AtomicReference<>();

/**
 * 记录锁重入次数
 */
private volatile int count = 0;
//volatile对其他线程的可见性

 public void lock(){
     Thread thread = Thread.currentThread();
     if (thread == owner.get()){//获取AtomicReference的当前对象引用值。
         count ++;
         return;
     }
    /**
    原子性地更新AtomicReference内部的value值,
    其中expect代表当前AtomicReference的value值,update则是需要设置的新引用值。
    该方法会返回一个boolean的结果,
    当expect和AtomicReference的当前值不相等时,修改会失败,返回值为false,
    若修改成功则会返回true。
    **/
     while (!owner.compareAndSet(null,thread));
 }

 public void unlock(){
     Thread thread = Thread.currentThread();
     if (thread == owner.get()){
         if (count > 0) count --; //锁重入, 直接自减即可
         else owner.set(null);//设置AtomicReference最新的对象引用值,该新值的更新对其他线程立即可见。
     }
 }

 public static void main(String[] args) {
     TestController test = new TestController();
     Runnable runnable = new Runnable() {
         @Override
         public void run() {
             System.out.println(Thread.currentThread().getName() + "开始尝试获取自旋锁");
             test.lock();
             try {
                 System.out.println(Thread.currentThread().getName() + "获取到了自旋锁");
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             } finally {
                 test.unlock();
                 System.out.println(Thread.currentThread().getName() + "释放了了自旋锁");
             }
         }
     };
     Thread t1 = new Thread(runnable);
     Thread t2 = new Thread(runnable);
     Thread t3 = new Thread(runnable);
     t1.start();
     t2.start();
     t3.start();
 }

java 公平锁自旋锁

代码语言:java
AI代码解释
复制
/**
 * 当前持有锁的号码
 */
private AtomicInteger serviceNum = new AtomicInteger(0);

/**
 * 记录锁重入次数
 */
private volatile int count = 0;//volatile对其他线程的可见性

/**
 * 排队号码
 */
private AtomicInteger ticketNum = new AtomicInteger(0);

/**
 * 各线程存放自己所申请的排队号码
 */
private static ThreadLocal<Integer> threadLocalNum = new ThreadLocal<>();


public void lock(){
    Integer num = threadLocalNum.get();
    if (num != null && num == serviceNum.get()){
        //当前线程已经持有锁, 则记录重入次数即可
        count ++;
        return;
    }

    //申请一个排队号码
    num = requestTickerNum();
    System.out.println("申请一个排队号码:"+num);
    threadLocalNum.set(num);

    //自旋等待,直到该排队号码与serviceNum相等
    while (num != this.serviceNum.get());
}

private Integer requestTickerNum() {
    return ticketNum.getAndIncrement();
}


public void unlock(){
    Integer num = threadLocalNum.get();
    if (num != null && num == serviceNum.get()){
        if (count > 0) count--;//锁重入, 直接自减即可
        else{
            threadLocalNum.remove();
            //自增serviceNum, 以便下一个排队号码的线程能够退出自旋
            serviceNum.set(num + 1);
        }
    }
}

public static void main(String[] args) {
    TestController test = new TestController();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "开始尝试获取自旋锁");
            test.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "获取到了自旋锁");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                test.unlock();
                System.out.println(Thread.currentThread().getName() + "释放了了自旋锁");
            }
        }
    };
    Thread t1 = new Thread(runnable);
    Thread t2 = new Thread(runnable);
    Thread t3 = new Thread(runnable);
    Thread t4 = new Thread(runnable);
    t1.start();
    t2.start();
    t3.start();
    t4.start();
}

7. 同步锁和死锁

7.1 同步锁

当多个线程同时访问同一个数据时,容易出现问题,为了避免,要保证线程同步互斥(指并发执行的多个线程),在同一时间内值允许一个线程访问共享数据。使用synchronized来获取一个对象的同步锁

7.2 死锁

多个线程同时被阻塞,他们中的一个或者全部都在等待某个资源被释放

产生死锁的条件:(下面同时存在才是死锁)

  1. 互斥条件:资源不能被共享,只能被同一个进程使用
  2. 请求与保持条件:已经得到的资源进程可以申请新的资源
  3. 非剥夺条件:已经分配的资源不能从相应的进程中被强制剥夺
  4. 循环等待条件:系统中若干进程组成环路,该环路中每个进程都在等待相邻进程占用的资源

常见死锁例子:进程a中包含资源a,进程b中包含资源b,a的下一步需要资源b,b的下一步需要资源a,所以他们就互相等待对方占有的资源释放,所以产生一个循环等待死锁

解决方法:

  • 不管他,无视他
  • 检测死锁并恢复
  • 资源进行动态分配
  • 破除上面的死锁条件

产生死锁:

情况一:

代码语言:java
AI代码解释
复制
/**
 * 一个简单的死锁类
 * t1先运行,这个时候flag==true,先锁定obj1,然后睡眠1秒钟
 * 而t1在睡眠的时候,另一个线程t2启动,flag==false,先锁定obj2,然后也睡眠1秒钟
 * t1睡眠结束后需要锁定obj2才能继续执行,而此时obj2已被t2锁定
 * t2睡眠结束后需要锁定obj1才能继续执行,而此时obj1已被t1锁定
 * t1、t2相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。 
 */
public class DeadLock implements Runnable{
    
    private static Object obj1 = new Object();
    private static Object obj2 = new Object();
    private boolean flag;
    
    public DeadLock(boolean flag){
        this.flag = flag;
    }
    
    @Override
    public void run(){
        System.out.println(Thread.currentThread().getName() + "运行");
        
        if(flag){
            synchronized(obj1){
                System.out.println(Thread.currentThread().getName() + "已经锁住obj1");
                try {  
                    Thread.sleep(1000);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
                synchronized(obj2){
                    // 执行不到这里
                    System.out.println("1秒钟后,"+Thread.currentThread().getName()
                                + "锁住obj2");
                }
            }
        }else{
            synchronized(obj2){
                System.out.println(Thread.currentThread().getName() + "已经锁住obj2");
                try {  
                    Thread.sleep(1000);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
                synchronized(obj1){
                    // 执行不到这里
                    System.out.println("1秒钟后,"+Thread.currentThread().getName()
                                + "锁住obj1");
                }
            }
        }
    }

}
代码语言:java
AI代码解释
复制
public static void main(String[] args) {
         
         Thread t1 = new Thread(new DeadLock(true), "线程1");
         Thread t2 = new Thread(new DeadLock(false), "线程2");

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

情况二:

代码语言:java
AI代码解释
复制
public class SyncThread implements Runnable{
    
    private Object obj1;
    private Object obj2;
 
    public SyncThread(Object o1, Object o2){
        this.obj1=o1;
        this.obj2=o2;
    }
    
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        synchronized (obj1) {
            System.out.println(name + " acquired lock on "+obj1);
            work();
            synchronized (obj2) {
                System.out.println("After, "+name + " acquired lock on "+obj2);
                work();
            }
            System.out.println(name + " released lock on "+obj2);
        }
        System.out.println(name + " released lock on "+obj1);
        System.out.println(name + " finished execution.");
    }
    
    private void work() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
代码语言:java
AI代码解释
复制
public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();
 
        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
        Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
 
        t1.start();
        Thread.sleep(1000);
        t2.start();
        Thread.sleep(1000);
        t3.start();
 
    }

8. 线程管理

8.1 线程睡眠(sleep)

让当前正在执行的线程暂停一段时间,并进入阻塞状态(使用Thread.sleep()方法)

当睡眠结束后,重新进入到就绪状态。

代码语言:java
AI代码解释
复制
public static void main(String[] args) throws InterruptedException {  
     MyThread thread = new MyThread();
     thread.start();
     thread.sleep(1000);//睡眠的是mian线程,不是MyThread 线程
     Thread.sleep(10);
     for(int i=0;i<100;i++){  
        System.out.println("main"+i);  
    }  
 }

8.2 线程让步(yield)

让当前正在执行的线程暂停,让出cpu资源给其他线程。yield后进入就绪状态。(可能出现:线程调度器又将其调度出来重新进入到运行状态运行)

当调用yield()方法暂停后,优先级比当前线程相同或者高时,就绪状态的线程更有可能获得执行机会

代码语言:java
AI代码解释
复制
public class Test1 {  
    public static void main(String[] args) throws InterruptedException {  
        new MyThread("低级", 1).start();  
        new MyThread("中级", 5).start();  
        new MyThread("高级", 10).start();  
    }  
}  
  
    class MyThread extends Thread {  
    public MyThread(String name, int pro) {  
        super(name);// 设置线程的名称  
        this.setPriority(pro);// 设置优先级  
    }  
  
    @Override  
    public void run() {  
        for (int i = 0; i < 30; i++) {  
            System.out.println(this.getName() + "线程第" + i + "次执行!");  
            if (i % 5 == 0)  
                Thread.yield();  
        }  
    }  
} 

运行结果:先把高级的执行完再执行中级最后执行低级

sleep()和yield()的区别

  • sleep方法暂停当前线程后,会进入阻塞状态,只有当睡眠时间到了,才会转入就绪状态。而yield方法调用后 ,是直接进入就绪状态,所以有可能刚进入就绪状态,又被调度到运行状态。
  • sleep方法声明抛出了InterruptedException,所以调用sleep方法的时候要捕获该异常,或者显示声明抛出该异常。而yield方法则没有声明抛出任务异常。
  • sleep方法比yield方法有更好的可移植性,通常不要依靠yield方法来控制并发线程的执行。

8.3 线程合并(join)

将几个并行线程的线程合并为一个单线程执行,应用场景是当一个线程必须等待另一个线程执行完毕才能执行时,join方法可以完成这个功能。

代码语言:java
AI代码解释
复制
void join()      
     当前线程等该加入该线程后面,等待该线程终止。    
void join(long millis)  
     当前线程等待该线程终止的时间最长为 millis 毫秒。 如果在millis时间内,该线程没有执行完,
     那么当前线程进入就绪状态,重新等待cpu调度  
void join(long millis,int nanos)   
     等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。如果在millis时间内,该线程没有执行完,
     那么当前线程进入就绪状态,重新等待cpu调度

8.4 设置线程优先级

 每个线程执行时都有一个优先级的属性,优先级高的线程可以获得较多的执行机会,而优先级低的线程则获得较少的执行机会。与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的也并非没机会执行。

每个线程默认的优先级都与创建它的父线程具有相同的优先级,在默认情况下,main线程具有普通优先级。

注:Thread类提供了setPriority(int newPriority)和getPriority()方法来设置和返回一个指定线程的优先级,其中setPriority方法的参数是一个整数,范围是1~·0之间,也可以使用Thread类提供的三个静态常量:

  • MAX_PRIORITY = 10
  • MIN_PRIORITY = 1
  • NORM_PRIORITY = 5
代码语言:java
AI代码解释
复制
public class Test1 {  
        public static void main(String[] args) throws InterruptedException {  
            new MyThread("高级", 10).start();  
            new MyThread("低级", 1).start();  
        }  
    }  
      
    class MyThread extends Thread {  
        public MyThread(String name,int pro) {  
            super(name);//设置线程的名称  
            setPriority(pro);//设置线程的优先级  
        }  
        @Override  
        public void run() {  
            for (int i = 0; i < 100; i++) {  
                System.out.println(this.getName() + "线程第" + i + "次执行!");  
            }  
        }  
    }  

8.5 守护线程(setDaemon)

守护线程是指在程序运行的时候在后台提供一种通用服务的线程

 守护线程使用的情况较少,但并非无用,举例来说,JVM的垃圾回收、内存管理等线程都是守护线程。还有就是在做数据库应用时候,使用的数据库连接池,连接池本身也包含着很多后台线程,监控连接个数、超时时间、状态等等。调用线程对象的方法setDaemon(true),则可以将其设置为守护线程。守护线程的用途为:

  • 守护线程通常用于执行一些后台作业,例如在你的应用程序运行时播放背景音乐,在文字编辑器里做自动语法检查、自动保存等功能。
  • Java的垃圾回收也是一个守护线程。守护线的好处就是你不需要关心它的结束问题。例如你在你的应用程序运行的时候希望播放背景音乐,如果将这个播放背景音乐的线程设定为非守护线程,那么在用户请求退出的时候,不仅要退出主线程,还要通知播放背景音乐的线程退出;如果设定为守护线程则不需要了。

setDaemon方法的详细说明:

代码语言:java
AI代码解释
复制
public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。    
该方法必须在启动线程前调用。 该方法首先调用该线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)。   
  参数:
     on - 如果为 true,则将该线程标记为守护线程。    
  抛出:    
    IllegalThreadStateException - 如果该线程处于活动状态。    
    SecurityException - 如果当前线程无法修改该线程。

9. 线程同步

java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如增删改查),将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作前,被其他线程调用,从而保证该变量的唯一性和准确性。

9.1 同步方法

synchronized修饰方法,java每个对象都有一个内置锁,当用了synchronized修饰后,内置锁会保护整个方法。

代码语言:java
AI代码解释
复制
public synchronized void save(){}

synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类

9.2 同步代码块

synchronized关键字修饰的语句块。被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。

代码语言:java
AI代码解释
复制
public class Bank {  
     
    private int count =0;//账户余额  
 
    //存钱  
    public void addMoney(int money){   
        synchronized (this) {  
            count +=money;  
        }  
        System.out.println(System.currentTimeMillis()+"存进:"+money);  
    }  
 
    //取钱  
    public void subMoney(int money){   
        synchronized (this) {  
            if(count-money < 0){  
                System.out.println("余额不足");  
                return;  
            }  
            count -=money;  
        }  
        System.out.println(+System.currentTimeMillis()+"取出:"+money);  
    }  
 
    //查询  
    public void lookMoney(){  
        System.out.println("账户余额:"+count);  
    }
}

9.3 使用特殊域变量(volatile)实现同步

  • volatile关键字为域变量的访问提供了一种免锁机制;
  • 使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新;
  • 因此每次使用该域就要重新计算,而不是使用寄存器中的值;
  • volatile不会提供任何原子操作,它也不能用来修饰final类型的变量。
代码语言:java
AI代码解释
复制
public class SynchronizedThread {
 
 	class Bank {
        private volatile int account = 100;
        public int getAccount() {
            return account;
    	}

        /**
         * 用同步方法实现
         * 
         * @param money
         */
        public synchronized void save(int money) {
            account += money;
        }

        /**
         * 用同步代码块实现
         * 
         * @param money
         */
        public void save1(int money) {
            synchronized (this) {
                account += money;
            }
        }
    }

    class NewThread implements Runnable {
        private Bank bank;

        public NewThread(Bank bank) {
            this.bank = bank;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                // bank.save1(10);
                bank.save(10);
                System.out.println(i + "账户余额为:" +bank.getAccount());
            }
        }

    }

    /**
     * 建立线程,调用内部类
     */
    public void useThread() {
        Bank bank = new Bank();
        NewThread new_thread = new NewThread(bank);
        System.out.println("线程1");
        Thread thread1 = new Thread(new_thread);
        thread1.start();
        System.out.println("线程2");
        Thread thread2 = new Thread(new_thread);
        thread2.start();
    }

    public static void main(String[] args) {
        SynchronizedThread st = new SynchronizedThread();
        st.useThread();
    }
 }

9.4 使用重入锁(Lock)实现线程同步

在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。ReentrantLock类是可重入、互斥、实现了Lock接口的锁,它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。

ReenreantLock类的常用方法有:

  • ReentrantLock() : 创建一个ReentrantLock实例
  • lock() : 获得锁
  • unlock() : 释放锁
代码语言:java
AI代码解释
复制
//只给出要修改的代码,其余代码与上同
        class Bank {
            
            private int account = 100;
            //需要声明这个锁
            private Lock lock = new ReentrantLock();
            public int getAccount() {
                return account;
            }
            //这里不再需要synchronized 
            public void save(int money) {
                lock.lock();
                try{
                    account += money;
                }finally{
                    lock.unlock();
                }
                
            }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
b代码构成2-标识符
用户7865723
2023/10/18
2430
《Java从入门到失业》第三章:基础语法及基本程序结构(3.2-3.5):标识符、关键字、注释、变量及常量
       上面我们知道我们自定义一个类,需要一个类名。在Java中,还有很多需要命名的组成部分,例如方法名,变量名等。标识符的命名需要遵循Java的规范,总结如下:
用户7801119
2020/09/27
3970
Java学习之基础语法
任何一种计算机语言都离不开标识符和关键字,因此下面将详细介绍 Java 的标识符、关键字和保留字。
李小白是一只喵
2022/03/21
5240
Java学习之基础语法
Java基础-标识符Identifier
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
cwl_java
2019/11/12
5420
java标识符与关键字_4、Java标识符和关键字
标识符:Java对各种变量,方法和类等要素命名时使用的字符序列称为标识符。(凡是自己可以起名的地方都叫标识符,都遵循标识符的规则)
全栈程序员站长
2022/09/08
3100
java标记符_java标识符的书写规则
1.可以由字母,数字,下划线,美元符号组成,但是不能包含@,%,空格等其它特殊字符,不能以数字开头。
全栈程序员站长
2022/09/08
6490
【C语言】标识符大通关!
标识符是编程语言中的基本元素之一。在C语言中,标识符用于命名变量、函数、类型、标签等。正确理解和使用标识符对于编写可读性强、易维护的代码至关重要。
LuckiBit
2024/12/11
2370
Java 基础教学:基础语法 - 注释、标识符与关键字
Java是一种广泛使用的编程语言,它的语法规则和结构为编程提供了清晰的框架。为了编写出易于理解和维护的代码,必须掌握Java的基本语法元素,包括注释、标识符和关键字。本文档将详细介绍这些概念,并提供示例以帮助初学者了解和应用。
世间万物皆对象
2024/10/22
1640
java语言基础(关键字,标识符,命名规则)
Java标识符定义(标识符:凡是直接可以命名的地方) 1、 包名、类名、方法名、参数名、变量名等,这些符号被称为标识符。 2、 标识符可以由字母、数字、下划线(_)和美元符号($)组成 3、 标识符不能以数字开头,不能是java中的关键字。例如:
一个风轻云淡
2022/11/13
1.1K0
java语言基础(关键字,标识符,命名规则)
Java程序设计(基础)- 基本语法
标识符:给接口(interface)、变量(variables)、类(class)和方法(method)命名。
全栈程序员站长
2022/06/30
3420
Java程序设计(基础)- 基本语法
JAVA合法标识符
Java语言中,对于变量,常量,函数,语句块均有名字,我们统统称之为Java标识符.
全栈程序员站长
2022/09/08
1.2K0
Java基础入门篇(二)——Java注释、关键字和标识符
前面几篇文章用Java带大家一起了解了几个游戏小项目,感兴趣的小伙伴可以点击文章观摩下,手把手教你用Java打造一款简单故事书(上篇)、手把手教你用Java打造一款简单故事书(下篇)、手把手教你用Java打造一款简单考试系统(上篇)、手把手教你用Java打造一款简单考试系统(下篇)接下来的几篇文章是关于Java基础的,希望对大家的学习有帮助,欢迎大家在讨论区留言。
Java进阶者
2021/01/22
5420
java 标识符,分隔符,关键字[通俗易懂]
Java语言中,对于变量,常量,函数,语句块也有名字,我们统统称之为Java标识符. 标识符是用来给类、对象、方法、变量、接口和自定义数据类型命名的。
全栈程序员站长
2022/09/08
8040
JavaNote[001] - 注释、标识符、关键字、变量
Java学习的基础知识,因为之前学习过了就2倍速快速过了一下,下面是一些简单的笔记?,顺手就记录下来了。 1 注释 注释不会出现在字节码中,也就是说Java编译器编译的时候会忽略我们的注释内容,这样子
Sam Gor
2020/05/28
5360
【Java学习笔记之二】java标识符命名规范
什么是标识符 就是程序员在定义java程序时,自定义的一些名字。标识符可以应用在类名、变量、函数名、包名上。 标识符必须遵循以下规则 标识符由26个英文字符大小写(a~zA~Z)、数字(0~9)、下划线(_)和美元符号($)组成。 不能以数字开头,不能是关键字 严格区分大小写 标识符的可以为任意长度 Java中的标识符命名规范 1.  包名 多个单词组成时所有字母小写(例:package  com.baidu) 2.  类名和接口 多个单词组成时所有单词的首字母大写(例:HelloWorld) 3.   变
Angel_Kitty
2018/04/09
7270
java标识符是什么_Java 标识符「建议收藏」
标识符就是程序员在编写 Java 程序时,自定义的一些名字。例如第一个Java 程序里关键字 class 后跟的 HelloWorld,就是我们自定义的类名。类名就属于标识符的一种。
全栈程序员站长
2022/09/08
8680
【Python】标识符 ( Python 标识符命名规则 - 强制性 | 内容限定 | 大小写敏感 | 非关键字 | Python 标识符命名规范 - 建议性 | 下划线命名法 | 英文字母全小写 )
关键字大小写敏感 , 如果改变了关键字的大小写 , 就变成了标识符 , 不再是关键字了 ;
韩曙亮
2023/04/07
1.5K0
【Python】标识符 ( Python 标识符命名规则 - 强制性 | 内容限定 | 大小写敏感 | 非关键字 | Python 标识符命名规范 - 建议性 | 下划线命名法 | 英文字母全小写 )
上手python之数据类型转换和标识符
数据类型之间,在特定的场景下,是可以相互转换的,如字符串转数字、数字转字符串等 那么,我们为什么要转换它们呢?
一个风轻云淡
2022/11/15
8050
上手python之数据类型转换和标识符
JAVA自学-标识符、变量的来源
文章开始前,先问大家一个问题,你觉得什么方式能够让你更快接受、学习一门新的语言?
IT学习日记
2022/09/13
5770
JAVA自学-标识符、变量的来源
1.2 标识符与命名规则
小驼峰命名法:方法名、参数名、成员变量、局部变量;(receiptMessage)
ha_lydms
2023/08/09
3300
1.2 标识符与命名规则
推荐阅读
相关推荐
b代码构成2-标识符
更多 >
目录
  • 1. java线程实现/创建的方式(主要是两种)
  • 2. 线程的生命周期
  • 3. 终止线程的方式
  • 4. sleep和wait区别
  • 5.start和run区别
  • 6. 乐观锁、悲观锁和自旋锁
    • 6.1 乐观锁(AtomicInteger)
    • 6.2 悲观锁 ( synchronize lock)
    • 6.3 自旋锁
  • 7. 同步锁和死锁
    • 7.1 同步锁
    • 7.2 死锁
  • 8. 线程管理
    • 8.1 线程睡眠(sleep)
    • 8.2 线程让步(yield)
    • 8.3 线程合并(join)
    • 8.4 设置线程优先级
    • 8.5 守护线程(setDaemon)
  • 9. 线程同步
    • 9.1 同步方法
    • 9.2 同步代码块
    • 9.3 使用特殊域变量(volatile)实现同步
    • 9.4 使用重入锁(Lock)实现线程同步
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档