• Java并发(三)----创建线程的三种方式及查看进程线程


    一、直接使用 Thread

    // 创建线程对象
    Thread t = new Thread() {
        public void run() {
            // 要执行的任务
        }
    };
    // 启动线程
    t.start();

    例如:

    // 构造方法的参数是给线程指定名字,推荐
    Thread t1 = new Thread("t1") {
        @Override
        // run 方法内实现了要执行的任务
        public void run() {
            log.debug("hello");
        }
    };
    t1.start();

    输出

    19:19:00 [t1] c.ThreadStarter - hello

    注意:这里通过@Slf4j注解打印的日志

    二、使用 Runnable

    把【线程】和【任务】(要执行的代码)分开

    • Thread 代表线程

    • Runnable 可运行的任务(线程要执行的代码)

    Runnable runnable = new Runnable() {
        public void run(){
            // 要执行的任务
        }
    };
    // 创建线程对象
    Thread t = new Thread( runnable );
    // 启动线程
    t.start(); 

    例如:

    // 创建任务对象
    Runnable task2 = new Runnable() {
        @Override
        public void run() {
            log.debug("hello");
        }
    };
    ​
    // 参数1 是任务对象; 参数2 是线程名字,推荐
    Thread t2 = new Thread(task2, "t2");
    t2.start();

    输出

    19:19:00 [t2] c.ThreadStarter - hello

    Java 8 以后可以使用 lambda 精简代码

    // 创建任务对象
    Runnable task2 = () -> log.debug("hello");
    ​
    // 参数1 是任务对象; 参数2 是线程名字,推荐
    Thread t2 = new Thread(task2, "t2");
    t2.start();

    小结

    • 方法1 是把线程和任务合并在了一起,方法2 是把线程和任务分开了

    • 推荐使用用 Runnable,因为 更容易与线程池等高级 API 配合

    • 用 Runnable 让任务类脱离了 Thread 继承体系,更灵活

    三、FutureTask

    FutureTask (未来任务)能够接收 Callable 类型的参数,用来处理有返回结果的情况

    // 创建任务对象
    FutureTask task3 = new FutureTask<>(() -> {
        log.debug("hello");
        Thread.sleep(2000);
        return 100;
    });
    ​
    // 参数1 是任务对象; 参数2 是线程名字,推荐
    new Thread(task3, "t3").start();
    ​
    // 运行到这里主线程阻塞,会同步等待 task 执行完毕的结果
    Integer result = task3.get();
    log.debug("结果是:{}", result);

    输出

    19:22:27 [t3] c.ThreadStarter - hello
    19:22:29 [main] c.ThreadStarter - 结果是:100

    可以看到两秒后主线程返回结果

    四、观察多个线程同时运行

    主要是理解

    • 交替执行

    • 谁先谁后,线程的执行不由我们控制

    代码

        public static void main(String[] args) {
            new Thread(() -> {
                while(true) {
                    log.debug("running");
                }
            },"t1").start();
            new Thread(() -> {
                while(true) {
                    log.debug("running");
                }
            },"t2").start();
        }

    结果

    可以看到,线程是交替运行的。但是谁先谁后不是我们控制的。但是如果是单核CPU的话运行这段程序的话,只会有一个线程开始运行。

    五、查看进程线程

    5.1 windows

    • 任务管理器可以查看进程和线程数,也可以用来杀死进程

    • 控制台tasklist 查看进程

    • 控制台taskkill /F /PID pid编号 杀死进程

    5.2 linux

    • ps -fe 查看所有进程

    • ps -fe | grep 关键词 查看所有进程

    • ps -fT -p 查看某个进程(PID)的所有线程

    • kill 杀死进程

    • top 按大写 H 切换是否显示线程

    • top -H -p 查看某个进程(PID)的所有线程,可持续查看线程的状态

    5.3 Java

    • jps 命令查看所有 Java 进程

    • jstack 查看某个 Java 进程(PID)的所有线程状态 ,只能查看某一刻某个进程所有线程较详细的状态

    • jconsole 来查看某个 Java 进程中线程的运行情况(图形界面)

    • 如果是从命令行启动,使 JDK 在 PATH 上,运行 jconsole 即可;如果从 GUI shell 启动,找到 JDK 安装路径,打开 bin 文件夹,双击 jconsole

      jconsole 远程监控配置

    • 需要以如下方式运行你的 java 类

    java -Djava.rmi.server.hostname=`ip地址` -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=`连接端口` -Dcom.sun.management.jmxremote.ssl=是否安全连接 -Dcom.sun.management.jmxremote.authenticate=是否认证 java类
    • 修改 /etc/hosts 文件将 127.0.0.1 映射至主机名

    如果要认证访问,还需要做如下步骤

    • 复制 jmxremote.password 文件

    • 修改 jmxremote.password 和 jmxremote.access 文件的权限为 600 即文件所有者可读写

    • 连接时填入 controlRole(用户名),R&D(密码)

    这种方式了解一下即可。对于生产环境一般没有权限访问的。

     

     



    如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    【知识点随笔分析 | 第六篇】HTTP/1.1,HTTP/2和HTTP/3的区别
    洛谷-收集邮票-(期望dp+期望的平方+平方的期望)
    flutter 系列之:flutter 中的幽灵offstage
    【Java面试】带你从面试官的角度深入剖析,什么是Java虚拟机为什么要使用?
    使用Zipkin与Spring Cloud Sleuth进行分布式跟踪
    基于随机森林实现特征选择降维及回归预测(Matlab代码实现)
    gitlab的安装与迁移
    详解设计模式:策略模式
    redisson使用过程常见问题汇总
    分布式缓存NCache使用
  • 原文地址:https://www.cnblogs.com/xiaoyh/p/16964632.html