迅速读懂Java线程的交通规则 | 带你学《Java语言高级特性》之八

简介: 线程就像现实世界里复杂的交通线上运行的汽车,有停车让行的,也有一路高歌的,甚至还有特殊情况优先行驶的情况,本节将一一介绍这些内容。

上一篇:教你随心操控线程状态 | 带你学《Java语言高级特性》之七
【本节目标】
通过阅读本节内容,你将学会使用join方法让线程强制一直执行、使用yield方法礼让其他线程优先执行,了解并学会设置线程的优先级使系统自动调度资源执行线程。

线程的强制执行

所谓的线程的强制执行指的是当满足于某些条件之后,某一个线程对象将可以一直独占资源,一直到该线程的程序执行结束。
范例:观察一个没有强制执行的程序

public class ThreadDemo {
   public static void main(String[] args) throws Exception {
       Thread thread = new Thread(() -> {
           for (int x = 0; x < 100; x++) {
               try {
                   Thread.sleep(100);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.println(Thread.currentThread().getName() + "执行、x = " + x);
           }
       }, "玩耍的线程");
       thread.start();
       for (int x = 0; x < 100; x++) {
           Thread.sleep(100);
           System.out.println("【霸道的main线程】number = " + x);
       }
   }
}

image.png
图一 没有强制执行的程序

这个时候主线程和子线程都在交替执行着,但是如果说现在希望主线程独占执行,那么就可以用Thread类中的方法:

强制执行 :public final void join(long millis) throws InterruptedException;
public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        Thread mainThread = Thread.currentThread();    //获得主线程
        Thread thread = new Thread(() -> {
            for (int x = 0; x < 100; x++) {
                if (x == 3) {      //现在霸道的线程来了
                    try {
                        mainThread.join();    //霸道的线程要先执行
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "执行、x = " + x);
            }
        }, "玩耍的线程");
        thread.start();
        for (int x = 0; x < 100; x++) {
            Thread.sleep(100);
            System.out.println("【霸道的main线程】number = " + x);
        }
    }
}

image.png
图二 强制执行

在进行线程强制执行的时候,一定要获取强制执行线程对象之后才可以执行join()的调用。

线程礼让

线程的礼让指的是先将资源让出去让别的线程先执行。线程的礼让可以使用Thread类中提供的方法:

public static void yield();

范例:使用礼让操作

public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(() -> {
            for (int x = 0; x < 100; x++) {
                if(x%3==0){
                    Thread.yield();      //线程礼让
                    System.out.println("### 玩耍的线程礼让执行 ###");
                }
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "执行、x = " + x);
            }
        }, "玩耍的线程");
        thread.start();
        for (int x = 0; x < 100; x++) {
            Thread.sleep(100);
            System.out.println("【霸道的main线程】number = " + x);
        }
    }
}

image.png
图三 礼让线程

礼让执行的时候每一次调用yield()方法都只会礼让一次当前的资源。

线程优先级

从理论上来讲,线程的优先级越高,越有可能先执行(越有可能先抢占到资源)。在Thread类中针对优先级的操作提供有如下两个处理方法:

设置优先级:public final void setPriority(int newPriority);
获取优先级:public final int getPriority();

在进行优先级定义的时候都是通过int型的数字来完成的,而对于此数字的选择在Thread类中就定义了三个常量:

最高优先级:public static final int MAX_PRIORITY 、10;
中等优先级:public static final int NORM_PRIORITY 、5;
最低优先级:public static final int MIN_PRIORITY 、1;

范例:观察优先级

public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        Runnable run = () -> {
            for (int x = 0; x < 10; x++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "执行。");
            }
        };
        Thread threadA = new Thread(run, "线程对象A");
        Thread threadB = new Thread(run, "线程对象B");
        Thread threadC = new Thread(run, "线程对象C");
        threadA.setPriority(Thread.MIN_PRIORITY);
        threadB.setPriority(Thread.MIN_PRIORITY);
        threadC.setPriority(Thread.MAX_PRIORITY);
        threadA.start();
        threadB.start();
        threadC.start();
    }
}

image.png
图四 线程优先级执行

主方法是一个主线程,那么主线程的优先级呢?默认线程对象的优先级呢?

public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        System.out.println(Thread.currentThread().getPriority());    //5
        System.out.println(new Thread().currentThread().getPriority());    //5
    }
}

主线程属于中等优先级,而默认创建的线程也是中等优先级。

想学习更多的Java的课程吗?从小白到大神,从入门到精通,更多精彩不容错过!免费为您提供更多的学习资源。
本内容视频来源于阿里云大学

下一篇:使用同步解决多人卖票问题 | 带你学《Java语言高级特性》之九
更多Java面向对象编程文章查看此处

相关文章
|
7月前
|
安全 Java
Java异常处理:程序世界的“交通规则
Java异常处理:程序世界的“交通规则
382 98
|
12月前
|
Java 开发者 Kotlin
华为仓颉语言初识:并发编程之线程的基本使用
本文详细介绍了仓颉语言中线程的基本使用,包括线程创建(通过`spawn`关键字)、线程名称设置、线程执行控制(使用`get`方法阻塞主线程以获取子线程结果)以及线程取消(通过`cancel()`方法)。文章还指出仓颉线程与Java等语言的差异,例如默认不提供线程名称。掌握这些内容有助于开发者高效处理并发任务,提升程序性能。
371 2
|
7月前
|
存储 Java Go
【Java】(3)8种基本数据类型的分析、数据类型转换规则、转义字符的列举
牢记类型转换规则在脑海中将编译和运行两个阶段分开,这是两个不同的阶段,不要弄混!
340 2
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
326 2
|
Java 程序员
java基础(5)标识符命名规则和命名规范
Java标识符命名规则包括只能使用数字、字母、下划线\_、$,且数字不能开头,不能使用关键字命名,且严格区分大小写。命名规范建议类名、接口名首字母大写,变量名、方法名首字母小写,常量名全大写。
688 2
|
10月前
|
存储 数据采集 数据可视化
Java 大视界 -- 基于 Java 的大数据可视化在城市交通拥堵溯源与治理策略展示中的应用(191)
本项目探索了基于Java的大数据可视化技术在城市交通拥堵溯源与治理策略中的应用。通过整合多源交通数据,利用Java生态中的大数据处理与可视化工具,构建了交通拥堵分析模型,并实现了拥堵成因的直观展示与治理效果的可视化评估。该方案为城市交通管理提供了科学、高效的决策支持,助力智慧城市建设。
|
存储 安全 算法
Go语言是如何支持多线程的
【10月更文挑战第21】Go语言是如何支持多线程的
352 72
|
Java
Java源文件声明规则详解
Java源文件的声明规则是编写清晰、可读且符合语法规范的Java程序的基础。这些规则包括文件名必须与公共类名相同、包声明位于文件顶部、导入声明紧跟其后、类声明需明确访问级别,并允许使用注释增强代码可读性。一个源文件可包含多个类,但只能有一个公共类。遵循这些规则有助于提升代码质量和维护性。
465 28
|
Go 调度 开发者
Go语言多线程的优势
【10月更文挑战第15天】
234 4
|
存储 Java API
优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。
【10月更文挑战第19天】本文介绍了如何优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。内容包括Map的初始化、使用Stream API处理Map、利用merge方法、使用ComputeIfAbsent和ComputeIfPresent,以及Map的默认方法。这些技巧不仅提高了代码的可读性和维护性,还提升了开发效率。
602 3

热门文章

最新文章