百丈高楼平地起,要想学好多线程,首先还是的了解一下线程的基础,这边文章将带着大家来了解一下线程的基础知识。

作者:小九

01、简介

百丈高楼平地起,要想学好多线程,首先还是的了解一下线程的基础,这边文章将带着大家来了解一下线程的基础知识。

02、线程的创建方式

  1. 实现 Runnable 接口
  2. 继承 Thread 类
  3. 实现 Callable 接口通过 FutureTask 包装器来创建线程
  4. 通过线程池创建线程

下面将用线程池和 Callable 的方式来创建线程

public class CallableDemo implements Callable<String> { @Override public String call() throws Exception { int a=1; int b=2; System. out .println(a+b); return "执行结果:"+(a+b); } public static void main(String[] args) throws ExecutionException, InterruptedException { //创建一个可重用固定线程数为1的线程池 ExecutorService executorService = Executors.newFixedThreadPool (1); CallableDemo callableDemo=new CallableDemo(); //执行线程,用future来接收线程的返回值 Future<String> future = executorService.submit(callableDemo); //打印线程的返回值 System. out .println(future.get()); executorService.shutdown(); } } 

执行结果

  1. 执行结果:3

03、线程的生命周期

  1. NEW:初始状态,线程被构建,但是还没有调用 start 方法。
  2. RUNNABLED:运行状态,JAVA 线程把操作系统中的就绪和运行两种状态统一称为“运行中”。调用线程的 start() 方法使线程进入就绪状态。
  3. BLOCKED:阻塞状态,表示线程进入等待状态,也就是线程因为某种原因放弃了 CPU 使用权。比如访问 synchronized 关键字修饰的方法,没有获得对象锁。
  4. Waiting :等待状态,比如调用 wait() 方法。
  5. TIME_WAITING:超时等待状态,超时以后自动返回。比如调用 sleep(long millis) 方法
  6. TERMINATED:终止状态,表示当前线程执行完毕。

看下源码:

public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED;
} 

04、线程的优先级

  1. 线程的最小优先级:1
  2. 线程的最大优先级:10
  3. 线程的默认优先级:5
  4. 通过调用 getPriority() 和 setPriority(int newPriority) 方法来获得和设置线程的优先级

看下源码:

/** * The minimum priority that a thread can have. */ public final static int MIN_PRIORITY = 1; /** * The default priority that is assigned to a thread. */ public final static int NORM_PRIORITY = 5; /** * The maximum priority that a thread can have. */ public final static int MAX_PRIORITY = 10;

看下代码:

public class ThreadA extends Thread { public static void main(String[] args) { ThreadA a = new ThreadA(); System.out.println(a.getPriority());//5 a.setPriority(8); System.out.println(a.getPriority());//8 }
} 

线程优先级特性:

  1. 继承性:比如 A 线程启动 B 线程,则B线程的优先级与 A 是一样的。
  2. 规则性:高优先级的线程总是大部分先执行完,但不代表高优先级线程全部先执行完。
  3. 随机性:优先级较高的线程不一定每一次都先执行完。

05、线程的停止

  1. stop() 方法,这个方法已经标记为过时了,强制停止线程,相当于 kill -9。
  2. interrupt() 方法,优雅的停止线程。告诉线程可以停止了,至于线程什么时候停止,取决于线程自身。

看下停止线程的代码:

public class InterruptDemo { private static int i ; public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { //默认情况下isInterrupted 返回 false、通过 thread.interrupt 变成了 true while (!Thread.currentThread().isInterrupted()) { i++; } System.out.println("Num:" + i); }, "interruptDemo"); thread.start(); TimeUnit.SECONDS.sleep(1); thread.interrupt(); //不加这句,thread线程不会停止 } 

看上面这段代码,主线程 main 方法调用 thread线程的 interrupt() 方法,就是告诉 thread 线程,你可以停止了(其实是将 thread 线程的一个属性设置为了 true ),然后 thread 线程通过 isInterrupted() 方法获取这个属性来判断是否设置为了 true。这里我再举一个例子来说明一下,

看代码:

public class ThreadDemo { private volatile static Boolean interrupt = false ; private static int i ; public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { while (!interrupt) { i++; } System.out.println("Num:" + i); }, "ThreadDemo"); thread.start(); TimeUnit.SECONDS.sleep(1); interrupt = true; }
} 

是不是很相似,再简单总结一下:

当其他线程通过调用当前线程的 interrupt 方法,表示向当前线程打个招呼,告诉他可以中断线程的执行了,并不会立即中断线程,至于什么时候中断,取决于当前线程自己。

线程通过检查自身是否被中断来进行相应,可以通过 isInterrupted() 来判断是否被中断。

这种通过标识符来实现中断操作的方式能够使线程在终止时有机会去清理资源,而不是武断地将线程停止,因此这种终止线程的做法显得更加安全和优雅。

06、线程的复位

两种复位方式:

  1. Thread.interrupted()
  2. 通过抛出 InterruptedException 的方式

然后了解一下什么是复位:

线程运行状态时 Thread.isInterrupted() 返回的线程状态是 false,然后调用 thread.interrupt() 中断线程 Thread.isInterrupted() 返回的线程状态是 true,最后调用 Thread.interrupted() 复位线程Thread.isInterrupted() 返回的线程状态是 false 或者抛出 InterruptedException 异常之前,线程会将状态设为 false。

下面来看下两种方式复位线程的代码,首先是 Thread.interrupted() 的方式复位代码:

public class InterruptDemo { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { while (true) { //Thread.currentThread().isInterrupted()默认是false,当main方式执行thread.interrupt()时,状态改为true if (Thread.currentThread().isInterrupted()) { System.out.println("before:" + Thread.currentThread().isInterrupted());//before:true Thread.interrupted(); // 对线程进行复位,由 true 变成 false System.out.println("after:" + Thread.currentThread().isInterrupted());//after:false } } }, "interruptDemo"); thread.start(); TimeUnit.SECONDS.sleep(1); thread.interrupt(); }
} 

抛出 InterruptedException 复位线程代码:

public class InterruptedExceptionDemo { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); // break; } } }, "interruptDemo"); thread.start(); TimeUnit.SECONDS.sleep(1); thread.interrupt(); System.out.println(thread.isInterrupted()); }
} 

结果:

  1. false
  2. java.lang.InterruptedException: sleep interrupted
  3. at java.lang.Thread.sleep(Native Method)
  4. at java.lang.Thread.sleep(Thread.java:340)
  5. at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
  6. at com.cl.concurrentprogram.InterruptedExceptionDemo.lambda$main$0(InterruptedExceptionDemo.java:16)
  7. at java.lang.Thread.run(Thread.java:748)

需要注意的是,InterruptedException 异常的抛出并不意味着线程必须终止,而是提醒当前线程有中断的操作发生,至于接下来怎么处理取决于线程本身,比如

  1. 直接捕获异常不做任何处理
  2. 将异常往外抛出
  3. 停止当前线程,并打印异常信息

像我上面的例子,如果抛出 InterruptedException 异常,我就break跳出循环让 thread 线程终止。

为什么要复位:

Thread.interrupted() 是属于当前线程的,是当前线程对外界中断信号的一个响应,表示自己已经得到了中断信号,但不会立刻中断自己,具体什么时候中断由自己决定,让外界知道在自身中断前,他的中断状态仍然是 false,这就是复位的原因。

阅读目录(置顶)(长期更新计算机领域知识)

阅读目录(置顶)(长期更新计算机领域知识)

阅读目录(置顶)(长期科技领域知识)

歌谣带你看java面试题

第九十三期:带你聊聊 Java 并发编程之线程基础相关推荐

  1. 独特视角带你走进Java并发编程的世界

    独特视角带你走进Java并发编程的世界 全局概括 并发问题产生的三个根本原因 java内存模型: 有序性和可见性的解决方案 volatile关键字 Happens-Before规则 锁: 原子性的解决 ...

  2. (转)Java并发编程:线程池的使用

    背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...

  3. 【Java 并发编程】线程池机制 ( ThreadPoolExecutor 线程池构造参数分析 | 核心线程数 | 最大线程数 | 非核心线程存活时间 | 任务阻塞队列 )

    文章目录 前言 一.ThreadPoolExecutor 构造参数 二.newCachedThreadPool 参数分析 三.newFixedThreadPool 参数分析 四.newSingleTh ...

  4. 【Java 并发编程】线程池机制 ( 线程池示例 | newCachedThreadPool | newFixedThreadPool | newSingleThreadExecutor )

    文章目录 前言 一.线程池示例 二.newCachedThreadPool 线程池示例 三.newFixedThreadPool 线程池示例 三.newSingleThreadExecutor 线程池 ...

  5. java并发编程与线程安全

    2019独角兽企业重金招聘Python工程师标准>>> 什么是线程安全 如果对象的状态变量(对象的实例域.静态域)具有可变性,那么当该对象被多个线程共享时就的考虑线程安全性的问题,否 ...

  6. 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  7. JAVA并发编程3_线程同步之synchronized关键字

    在上一篇博客里讲解了JAVA的线程的内存模型,见:JAVA并发编程2_线程安全&内存模型,接着上一篇提到的问题解决多线程共享资源的情况下的线程安全问题. 不安全线程分析 public clas ...

  8. [转]Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  9. Java并发编程:线程的同步

    <?xml version="1.0" encoding="utf-8"?> Java并发编程:线程的同步 Java并发编程:线程的同步 Table ...

最新文章

  1. VC++ OCX 控件注册
  2. Android 编译期间 动态修改AndroidMainFest文件
  3. 将NumPy数组转储到csv文件中
  4. ARP协议,以及ARP欺骗
  5. 企业中的微服务:敌是友?
  6. STM32F7xx —— QSPI
  7. 图文详解mina框架
  8. 服务器内存不认硬盘_服务器品牌有哪些?如何选择服务器?
  9. 如果没有英语,计算机,如果有一天没有电脑(英语作文)
  10. The ‘state_publisher‘ executable is deprecated. Please use ‘robot_state_publisher‘ instead
  11. Ibatis 动态查询
  12. WifiConfiguration 的各字段的填充和修改
  13. cuda-gdb 调试python中的module/cu文件
  14. FTP客户端-C++
  15. Java程序与设计11_一些题目
  16. 目标检测中的常见指标
  17. 计算机毕业设计ssm焦虑自测与交流平台k43cf系统+程序+源码+lw+远程部署
  18. 空指针引用,导致linux内核panic(重启)
  19. Verilog设计4位CLA加法器电路,并仿真测试
  20. 想要从编程小白成为达人,这些你必须知道!(附STM32学习指南)

热门文章

  1. 使用windows资源管理器打开jar
  2. [导入]C# Tips 2 右键单击listBox时弹出右键菜单并选中单击的行
  3. 毕业论文计算机附录模板,毕业论文格式是什么,附录又是什么?
  4. linux线程出错,在线程应用程序(linux,pthreads)中读取文件大小时出错
  5. 输电线路巡检机器人PPT_“高空大师”来了!架空输电线路智能巡检机器人在宁波投运...
  6. python语言用什么关键字来声明一个类_python使用什么关键字定义类
  7. 江苏省高等学校计算机一级成绩查询,江苏计算机一级考试成绩查询
  8. linux telnet smtp,如何使用Telnet测试IMAP与SMTP
  9. byte数组穿换成pcm格式_形象地介绍DSD的编解码原理及和PCM的区别
  10. 深度学习修炼(二)——数据集的加载