一、直接使用 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<Integer> 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> 查看某个进程(PID)的所有线程

  • kill 杀死进程

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

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

5.3 Java

  • jps 命令查看所有 Java 进程

  • jstack <PID> 查看某个 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(密码)

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

Java并发(三)----创建线程的三种方式及查看进程线程的更多相关文章

  1. Java并发和多线程2:3种方式实现数组求和

    本篇演示3个数组求和的例子. 例子1:单线程例子2:多线程,同步求和(如果没有计算完成,会阻塞)例子3:多线程,异步求和(先累加已经完成的计算结果) 例子1-代码 package cn.fansuni ...

  2. Java 8 创建 Stream 的 10 种方式,我保证你受益无穷!

    之前栈长分享过 Java 8 一系列新特性的文章,其中重点介绍了 Stream. 获取上面这份 Java 8~12 系列新特性干货文章,请在微信搜索关注微信公众号:Java技术栈,在公众号后台回复:j ...

  3. 【java并发】传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...

  4. Java并发基础01. 传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...

  5. java的线程、创建线程的 3 种方式、静态代理模式、Lambda表达式简化线程

    0.介绍 线程:多个任务同时进行,看似多任务同时进行,但实际上一个时间点上我们大脑还是只在做一件事情.程序也是如此,除非多核cpu,不然一个cpu里,在一个时间点里还是只在做一件事,不过速度很快的切换 ...

  6. Java并发编程之CAS第三篇-CAS的缺点及解决办法

    Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...

  7. 那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结

    <Java并发编程实战>和<Java并发编程的艺术>           Executor框架小结 1.在线程中如何执行任务 (1)任务执行目标: 在正常负载情况下,服务器应用 ...

  8. Java创建线程的四种方式

    Java创建线程的四种方式 1.继承Thread类创建线程 定义Thread类的子类,并重写该类的run方法,run()方法的内容就是该线程执行的内容 创建Thread子类的实例,即创建了线程对象. ...

  9. 当阿里面试官问我:Java创建线程有几种方式?我就知道问题没那么简单

    这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家. 点赞再看,养成习惯~ 微信搜索[武哥聊编程],关注这个 Java 菜鸟. 昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的 ...

  10. 网络编程:多进程实现TCP服务端并发、互斥锁代码实操、线程理论、创建线程的两种方式、线程的诸多特性、GIL全局解释器锁、验证GIL的存在

    目录 多进程实现TCP服务端并发 互斥锁代码实操 线程理论 创建线程的两种方式 线程的诸多特性 GIL全局解释器锁 验证GIL的存在 GIL与普通互斥锁 python多线程是否有用 死锁现象 多进程实 ...

随机推荐

  1. PHP 合并两个二维数组

    思路:遍历二维数组,合并两个二维数组的值,赋值给新数组 function mergeArray($arr1,$arr2){ $newArr = []; foreach($arr1 as $v1){ f ...

  2. [Unity工具]搭建lua环境(IDEA)

    一.下载IDEA 地址:https://www.jetbrains.com/idea/ 这里我的版本是IntelliJ IDEA Community Edition 2020.2.4 x64 二.断点 ...

  3. el-admin登录详解

    1.进入登陆界面后,就会自动获取验证码. 2.前端访问auth/code接口获取后端生成的验证码(包括uuid,img,结果值),然后放入redis,设置2分钟过期,并返回识别码.图片url给前端. ...

  4. LaTeX in 24 Hours - 书籍信息

    书籍信息 书名: LaTex in 24 Hours: A Practical Guide for Scientific Writing 作者: Dilip Datta 出版日期: 2017 ISBN ...

  5. ESP32 IDF V5.0 编译环境

    方法:环境搭建工具一键安装: 下载链接:https://dl.espressif.com/dl/esp-idf/ 可以选择离线安装方式和在线安装方式,建议:采用离线安装的方式 下载离线安装包之后点击安 ...

  6. mysql 不包含某个字符

    转载网址: https://blog.csdn.net/mp624183768/article/details/121696040?utm_medium=distribute.pc_relevant. ...

  7. 图像主题颜色提取(Median cut)

    前言 之前想对图片素材进行分类管理,除了打标签,还有一样是通过主题色进行分类.于是开始寻找能提取主主题色的工具,最后找到了大名鼎鼎的 Leptonica 库,其中就有中位切割算法的实现.下面附上中位切 ...

  8. 个人数据保全计划:(2) NAS基础知识

    前言 距离去年国庆入手了NAS至今有好几个月时间了,NAS折腾起来有点麻烦,且实际作用因人而异,并没有想象中的好用,所以说好的这个系列一直没有更新~ 还有另一方面的原因,这些NAS的系统基于Linux ...

  9. 一文快速回顾 Java 操作数据库的方式-JDBC

    前言 数据库的重要性不言而喻,不管是什么系统,什么应用软件,也不管它们是 Windows 上的应用程序,还是 Web 应用程序,存储(持久化)和查询(检索)数据都是核心的功能. 大家学习数据库时,比如 ...

  10. 加密脚本分析—evil.py

    加密脚本分析-evil.py 1.题目 源文件 一共两个文件 enc_flag.txt evil.py(原文件无注释) 1 # coding: utf-8 2 3 import base64 4 im ...