2024年Java最全Java多线程(一):线程的创建方式和常见构造方法以及常用属性,服务之间的调用为啥不直接用HTTP而用RPC

总结

本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解!

MySQL50道高频面试题整理:

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

public static void main(String[] args) {

    // 匿名内部类

    Thread thread = new Thread(new Runnable() {

        @Override

        public void run() {

            // 业务代码

            Thread t = Thread.currentThread();

            System.out.println("执行任务:" + t.getName());

        }

    });

    // 启动线程

    thread.start();

}

}




运行结果:



![](https://img-blog.csdnimg.cn/04cd46e9b2d34195975cd63ed6a42cee.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



###  3.2.2 变种方法 2:匿名方式创建子对象



public class ThreadDemo7 {

public static void main(String[] args) {

    // 创建线程并初始化

    Thread thread = new Thread() {

        @Override

        public void run() {

            Thread t = Thread.currentThread();

            System.out.println("任务执行:" + t.getName());

        }

    };

    // 开启线程

    thread.start();



}

}




运行结果:



![](https://img-blog.csdnimg.cn/f25ba3833fb24ad086a4841061c3f8ad.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



### 3.2.3 变种方法 3:使用 Lambda 匿名 Runnable 方式 (支持 JDK 1.8+ 版本,推荐使用)



public class ThreadDemo6 {

public static void main(String[] args) {

    // 创建线程

    Thread thread = new Thread(() -> {

        // 具体业务

        Thread t = Thread.currentThread();

        System.out.println("任务执行:" + t.getName());

    });

    // 执行线程

    thread.start();

}

}




运行结果:



![](https://img-blog.csdnimg.cn/01651b5d028640dc938bcb603cc18508.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



3.3 创建方式3:带返回值的 Callable

------------------------



public class ThreadDemo8 {

public static void main(String[] args) throws ExecutionException, InterruptedException {

    // 创建 Callable 实例

    MyCallable myCallable = new MyCallable();

    // 用于接收 Callable 结果的对象

    FutureTask<Integer> futureTask = new FutureTask<>(myCallable);

    // 创建新线程

    Thread thread = new Thread(futureTask);

    // 启动线程

    thread.start();

    // 接收新线程执行的结果

    int result = futureTask.get();

    System.out.println(Thread.currentThread().getName() + "新线程返回的结果为:" + result);

}



private static class MyCallable implements Callable<Integer> {

    @Override

    public Integer call() {

        // 生成随机数0~9

        int randomNum = new Random().nextInt(10);

        System.out.println(Thread.currentThread().getName() + "随机数" + randomNum);

        return randomNum;

    }

}

}




运行结果:



![](https://img-blog.csdnimg.cn/5b83ab240ab34cd38ef0777baf9d194b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



**也可通过匿名 Callable 实现:**



public class ThreadDemo9 {

public static void main(String[] args) throws ExecutionException, InterruptedException {

    // FutureTask 用于获取线程的执行结果

    FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {

        @Override

        public String call() throws Exception {

            // 新线程执行的任务代码

            String[] strings = new String[]{"Java", "MySQL", "Python"};

            // 随机返回一个字符串

            String result = strings[new Random().nextInt(3)];

            System.out.println(Thread.currentThread().getName() + "字符串:" + result);

            return result;

        }

    });

    // 创建新线程

    Thread thread = new Thread(futureTask);

    // 启动线程

    thread.start();

    String result = futureTask.get();

    System.out.println(Thread.currentThread().getName() + "新线程的返回值:" + result);

}

}




 运行结果:



![](https://img-blog.csdnimg.cn/b1cd1d496dd340dda6ca17ad99cd23ea.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



 3.4 小结

-------



        创建线程有 3 大类实现方式、7 种实现方法,如果是 JDK 1.8 以上版本,**在不需要获得线程执行结果的情况下,推荐使用 Lambda 方式来创建线程**,因为它的写法足够简洁;**如果想要获取线程执行结果,可使用 FutureTask + Callable 的方式来实现**。



4\. 线程常见构造方法

============



![](https://img-blog.csdnimg.cn/06f171476ed748179454d1c771329c9d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



 **具体使用:**



Thread t1 = new Thread();

Thread t2 = new Thread(new MyRunnable());

Thread t3 = new Thread(“这是我的名字”);

Thread t4 = new Thread(new MyRunnable(), “这是我的名字”);




**线程分组的使用:**



public class ThreadDemo12 {

public static void main(String[] args) {

    // 创建一个线程分组(百米赛跑)

    ThreadGroup threadGroup = new ThreadGroup("thread-group");

    // 定义一个公共的线程任务

    Runnable runTask = new Runnable() {

        @Override

        public void run() {

            // 生成一个1-3的随机数

            int randomNum = (1 + new Random().nextInt(3));

            // 跑了n秒后到达终点

            try {

                Thread.sleep(1000 * randomNum);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

            // 得到执行此线程的方法

            Thread thread = Thread.currentThread();

            System.out.println(thread.getName() + "选手到达终点:" + randomNum + "s");

        }

    };

    // 线程(运动员)

    Thread t1 = new Thread(threadGroup, runTask);

    Thread t2 = new Thread(threadGroup, runTask);

    Thread t3 = new Thread(threadGroup, runTask);



    // 启动线程(开跑)

    t1.start();

    t2.start();

    t3.start();



    // 所有人到达终点后宣布成绩

    while (threadGroup.activeCount() > 0) {

    }

    System.out.println("宣布比赛成绩");

}

}




5\. 线程常用属性

==========



![](https://img-blog.csdnimg.cn/0684ee0ae6cc4489910625aea1d9a35e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)

===============================================================================================================================================================================================



*    ID 是线程的唯⼀标识,不同线程不会重复。

*   名称 是各种调试⼯具用到。

*   状态 表示线程当前所处的⼀个情况。

*   优先级 高的线程理论上来说更容易被调度到。

*   关于守护线程(后台线程),需要记住⼀点:**JVM会在⼀个进程的所有非后台线程结束后,才会结束运行。**

*   是否存活,即简单的理解为 run 方法是否运行结束了。

*   线程的中断问题,下面我们进⼀步说明。



5.1 优先级

-------



> 优先级是 int 类型值,线程优先级1-10,**最小优先级是1,最大优先级是10,默认优先级是5**。



![](https://img-blog.csdnimg.cn/dae0542d960b4d8c93e136be32638e0b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



示例代码:



public class ThreadDemoByPriority2 {

private final static int MAX_COUNT = 1000;



public static void main(String[] args) {

    Thread t1 = new Thread(() -> {

        Thread t = Thread.currentThread();

        int priority = t.getPriority();

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

            System.out.println(t.getName() + "线程优先级:" + priority);

        }

    }, "线程1");

    // 设置线程优先级(10)

    t1.setPriority(Thread.MAX_PRIORITY);



    Thread t2 = new Thread(() -> {

        Thread t = Thread.currentThread();

        int priority = t.getPriority();

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

            System.out.println(t.getName() + "线程优先级:" + priority);

        }

    }, "线程2");

    // 设置线程优先级(5)

    t2.setPriority(Thread.NORM_PRIORITY);



    Thread t3 = new Thread(() -> {

        Thread t = Thread.currentThread();

        int priority = t.getPriority();

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

            System.out.println(t.getName() + "线程优先级:" + priority);

        }

    }, "线程3");

    // 设置线程优先级(1)

    t3.setPriority(Thread.MIN_PRIORITY);



    // 同时启动线程

    t3.start();

    t2.start();

    t1.start();

}

}




 运行结果:



![](https://img-blog.csdnimg.cn/8a42bbed539f4b5b8e64eb4c6d217e93.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



**结论 :**同时启动多个线程,多个线程设置了不同的优先级,并不是一定是优先级高的执行完了再执行优先级低的,而是优先级高的线程获取到CPU时间片的概率更大,更容易被调度到。



5.2 守护线程

--------



### 5.2.1 线程中的分类:



*   **用户线程**:主线程main默认是用户线程。

*   **守护线程(后台线程**):为用户线程服务的,用户线程全部结束之后,守护线程会跟随结束。 



### 5.2.2 守护线程应用



        JVM 中的垃圾回收器就是典型的守护线程,程序运行的时候它也运行,当满足条件是进行垃圾回收,当所有线程执行完任务终止时它也会随着退出。



守护线程示例:



public class ThreadDemoByDaemon {

public static void main(String[] args) throws InterruptedException {

    // 得到当前的线程

    Thread thread = Thread.currentThread();

    System.out.println(thread.getName() + "是否是守护线程:" + thread.isDaemon());



    Thread t1 = new Thread(() -> {

        Thread thread1 = Thread.currentThread();

        System.out.println(thread1.getName() + "是否是守护线程:" + thread1.isDaemon());

        // 创建子线程

        Thread tt1 = new Thread(() -> {

            Thread thread2 = Thread.currentThread();

            System.out.println(thread2.getName() + "是否是守护线程:" + thread2.isDaemon());

        }, "子线程的子线程");

        tt1.start();



    }, "子线程");



    // 手动设置为守护线程

    t1.setDaemon(true);

    // 启动线程

    t1.start();



    Thread.sleep(1000);

}

}




执行结果:



![](https://img-blog.csdnimg.cn/e81a397c98034a7488c510816514ec62.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



 **结论** :



*   main线程默认是非守护线程(用户线程)。

*   在默认情况下,在用户线程中创建的子线程也是用户线程。

*   在守护线程中创建的子线程也是守护线程。



**注意** : 线程的类型不能在线程启动后再进行设置,会发生报错。



### 5.2.3 用户线程 VS 守护线程



/**

 * 守护线程

 */

private static void daemonThread() {

    Thread thread = new Thread(() -> {

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

            System.out.println("守护线程执行:" + i);

            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    });

    // 设置为守护线程

    thread.setDaemon(true);

    thread.start();

}



 运行结果:



![](https://img-blog.csdnimg.cn/edea0206321f493fa5e5bef010f5fdfd.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



/**

 * 用户线程

 */

private static void userThread() {

    Thread thread = new Thread(() -> {

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

            System.out.println("用户线程执行:" + i);

            try {

                Thread.sleep(500);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    });

    thread.start();

}



运行结果:



![](https://img-blog.csdnimg.cn/492c698d48d04da58ce2bb445e588767.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)



**结论** : 



*   JVM 会等待所有用户线程执行完之后再退出。

*   JVM 不会等待所有守护线程执行完之后再退出。



### 5.3 是否存活



public class ThreadDemoByAlive {

public static void main(String[] args) {

    Thread thread = new Thread(() -> {

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

            try {

                Thread.sleep(500);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

        System.out.println("1.线程执行完了");

    });

    thread.start();

    while (thread.isAlive()) {

    }

最后

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
在这里插入图片描述

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

static void main(String[] args) {

    Thread thread = new Thread(() -> {

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

            try {

                Thread.sleep(500);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

        System.out.println("1.线程执行完了");

    });

    thread.start();

    while (thread.isAlive()) {

    }

最后

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-wBWNvWut-1714858966687)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值