香雨站

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 78|回复: 0

Java多线程知识点详解——Java进阶系列(十二)

[复制链接]

2

主题

6

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2023-1-14 19:18:54 | 显示全部楼层 |阅读模式


欢迎来到全网最完整的Java入门系列教程!!!
本教程将包含基础知识、进阶知识、常用框架等,循序渐进地分享Java中必须掌握的知识和技术。跟着老K的教程每天学习一点,你会发现入门Java没有想象中那么难。
之前我们通过4期的内容分享了IO文件读写和它的实战。本期开始我们将进入Java进阶知识的最后一个模块知识——多线程.
实现多线程的方法有很多,我们会介绍三个最具代表性的实现方法:Thread类、Runnable接口和Callable接口。


如果你正在学习Java,不妨收藏这篇文章,或者关注我,定期收获与Java有关的知识和项目信息!
想要了解Java基础部分的课程内容,可以看我的专栏->
老K玩代码:[专栏]Java基础知识讲义系列
<hr/>

正式开始本期内容的分享:
一、Thread类

Thread类是控制多线程的类。
代码示例:
import java.util.Random;

public class ThreadDemo {
    public static void main(String[] args) {
        SubThread threadA = new SubThread();
        threadA.setName("A线程");
        SubThread threadB = new SubThread();
        threadB.setName("B线程");

        threadA.start();
        threadB.start();
    }

    static class SubThread extends Thread {

        @Override
        public void run() {
            int num = 0;
            for (int i = 1; i <= 5; i++) {
                num += new Random().nextInt(10);
                System.out.println(this.getName() + "在" + i + "时的累加和为" + num);
            }
        }
    }
}运行结果:
A线程在1时的累加和为0
B线程在1时的累加和为9
A线程在2时的累加和为6
B线程在2时的累加和为9
A线程在3时的累加和为8
B线程在3时的累加和为9
A线程在4时的累加和为15
B线程在4时的累加和为11
A线程在5时的累加和为19
B线程在5时的累加和为11说明:

  • 上例中,SubThread是Thread的子类,用于设置自定义的线程逻辑;
  • Thread线程是通过定义子类,重写内部方法run来实现自定义线程的,重写的run方法里就是自定义的执行逻辑;
  • Thread类及其子类,都包含start方法,用来启动当前线程;
  • 从上例的运行结果可以看出,A、B两个进程不是“先A后B”的顺序,而是交替执行,这体现了多线程的逻辑;
  • 由于多线程的执行存在随机性,加上上例中的线程逻辑中加入了随机数,所以每次执行的结果和顺序都不会一样。
<hr/>二、Runnable接口

Runnable是一种通过接口实现线程逻辑的方法,使用上和Thread类似,不同程序员习惯不同,不管Runnable还是Thread,都是实现线程的好方法。
示例代码:
import java.util.Random;

public class ThreadDemo {
    public static void main(String[] args) {
        Thread threadA = new Thread(new SubThread());
        threadA.setName("A线程");
        Thread threadB = new Thread(new SubThread());
        threadB.setName("B线程");

        threadA.start();
        threadB.start();
    }

    static class SubThread implements Runnable {

        @Override
        public void run() {
            int num = 0;
            for (int i = 1; i <= 5; i++) {
                num += new Random().nextInt(10);
                System.out.println(Thread.currentThread().getName() + "在" + i + "时的累加和为" + num);
            }
        }
    }
}运行结果:
A线程在1时的累加和为5
B线程在1时的累加和为8
A线程在2时的累加和为14
B线程在2时的累加和为17
A线程在3时的累加和为20
B线程在3时的累加和为17
A线程在4时的累加和为28
B线程在4时的累加和为18
A线程在5时的累加和为29
B线程在5时的累加和为21说明:

  • Runnable也有run方法,使用上和Thread的run相似;
  • Runnable可以通过作为Thread的构造参数实现线程功能;
  • Runnable接口的实现类没有start方法,要执行线程必须以参数方式传入Thread,利用Thread的start方法启动。
<hr/>三、Callable接口

使用Thread或者Runnable的时候,有一个缺陷:就是因为是继承父类方法重写,所以不能规定返回值,而Callable能比较好地解决这个问题。
示例代码:
import java.util.Random;
import java.util.concurrent.*;

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

        ExecutorService exe = Executors.newFixedThreadPool(3);
        SubThread threadA = new SubThread();
        threadA.name = "A线程";
        SubThread threadB = new SubThread();
        threadB.name = "B线程";

        Future<Integer> f1 = exe.submit(threadA);
        Future<Integer> f2 = exe.submit(threadB);

        exe.shutdown();

        System.out.println(threadA.name + "的总和为" + f1.get());
        System.out.println(threadB.name + "的总和为" + f2.get());
    }

    static class SubThread implements Callable<Integer> {
        public String name;

        @Override
        public Integer call() {
            int num = 0;
            for (int i = 1; i <= 5; i++) {
                num += new Random().nextInt(10);
                System.out.println(this.name + "在" + i + "时的累加和为" + num);
            }
            return num;
        }
    }
}运行结果:
A线程在1时的累加和为0
B线程在1时的累加和为9
A线程在2时的累加和为2
B线程在2时的累加和为18
A线程在3时的累加和为10
B线程在3时的累加和为22
A线程在4时的累加和为17
B线程在4时的累加和为30
A线程在5时的累加和为25
B线程在5时的累加和为30
A线程的总和为25
B线程的总和为30说明:

  • Callable接口可以有返回值,此处的泛型用来规范返回值的数据类型,此处为Integer;
  • ExecutorService是用来管理线程池的类,Executors是线程管理的一个核心类;
  • Executors.newFixedThreadPool可以固定线程池中线程数量,返回类型为ExecutorService;
  • Callable接口实现类,需要放在ExecutorService中通过submit方法启动;
  • submit的线程,返回的是一个Future类型的数据,Future里会包含Callable.call的返回值;
  • 通过Future的方法get,可以获取Callable.call的返回值,用以后续的程序;
  • ExecutorService由于是充当线程池的角色,所以不会因为线程结束而自动关闭,需要通过shutdown方法进行关闭。
<hr/>以上就是有关于Java多线程的三个最具代表性的实现方法。大家可以收藏这篇文章,多读几遍慢慢消化。
如果你对老K分享的内容有任何疑问,欢迎随时在评论区留言或者私信我。
本期的内容就分享到这里。
正在学习的小伙伴记得给老K一个赞哦,你的支持是我持续输出课程内容最大的动力!


Java进阶知识前十一课的内容,可点击下方获取:
老K玩代码:如何优雅的处理异常--Java进阶知识讲义系列(一)
老K玩代码:包装器类装箱与拆箱的艺术——Java进阶知识讲义系列(二)
老K玩代码:一文讲透Java字符串——Java进阶知识讲义系列(三)
老K玩代码:List的用法和实例详解——Java进阶知识讲义系列(四)
老K玩代码:Set的用法和实例详解——Java进阶知识讲义系列(五)
老K玩代码:Map的用法和实例详解——Java进阶知识讲义系列(六)
老K玩代码:常用集合的排序方法——Java进阶知识讲义系列(七)
老K玩代码:I/O流之File类的用法和实例详解——Java进阶知识讲义系列(八)
老K玩代码:I/O流之字节流的读写——Java进阶知识讲义系列(九)
老K玩代码:I/O流之字符流的读写——Java进阶知识讲义系列(十)
老K玩代码:I/O流实战应用精选:网络图片下载器——Java进阶系列(十一)

结束语

我是专注于开发领域的@老K玩代码 ,会持续生产关于如何学习编程语言的优质内容。
如果你想学习Java编程,或者想精进你的Java编程能力,可以关注我。
如果你对开发、编程有任何疑问或者有想了解的内容,而我暂时没有写到的,也欢迎随时来找我聊聊。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|香雨站

GMT+8, 2025-7-3 20:52 , Processed in 0.101956 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.. 技术支持 by 巅峰设计

快速回复 返回顶部 返回列表