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

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

作者:小九

 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面试题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/424246.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我们还有理想吗?

兴致勃勃从海边享受了几天,本来打算回来后在这里写上几篇.其中还准备了一篇名为"一千个不加班的理由".可笑的是今天就从梦中醒来.因为有几个项目要加快投标准备了.我唯一能做的是耸耸肩膀,公司的事情当然要做,现实就是现实!前几天和老同学突然谈起一个话题,别的行业的…

17. Letter Combinations of a Phone Number

1 题目理解 给定一个字符串string&#xff0c;字符范围是[2,9]之间的数字。数字表示电话上的一个按钮。返回字符串的可能所有组合方式。每个数字对应的字母如下图所示。 Example 1: Input: digits “23” Output: [“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”…

第九十四期:GitHub 发布 2019 年年度报告

GitHub 发布了 2019 年年度报告《The State of the Octoverse》&#xff0c;下边来看看一些主要数据。 作者&#xff1a;佚名 GitHub 发布了 2019 年年度报告《The State of the Octoverse》&#xff0c;下边来看看一些主要数据。 全球用户超过 4 千万 目前 GitHub 上有超过…

COM 组件设计与应用(十一)

COM 组件设计与应用&#xff08;十一&#xff09;IDispatch 及双接口的调用作者&#xff1a;杨老师 下载源代码一、前言 前段时间&#xff0c;由于工作比较忙&#xff0c;没有能及时地写作。其间收到了很多网友的来信询问和鼓励&#xff0c;在此一并表示感谢。咳......我也需…

39. Combination Sum

文章目录1题目理解2 回溯分析3 40. Combination Sum II3.1 延续39解题思路3.2 新思路3.3 递归计数的方式4 216. Combination Sum III1题目理解 Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of ca…

第九十五期:Python帮你识破双11的套路

一年一度的“双十一”又要来了&#xff0c;很多人已经开始摩拳擦掌&#xff0c;毕竟几天之后手还在不在就不好说了。 作者&#xff1a;清风小筑 各种社交软件也是跟着遭殃&#xff0c;整天就是“来帮我一起盖楼”&#xff0c;各种字体绕过屏蔽&#xff0c;什么奇葩的脑洞也出来…

客户端独立弹出详细的实现过程

拷贝粘贴以下代码段&#xff0c;保存为html文件&#xff0c;试试看效果如何吧。。。前几天贴子没写东西就搁在上面搁了几天&#xff0c;真不好意思。 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ><HTML><HEAD></HEAD>&…

Unity3D性能优化之Draw Call Batching

在屏幕上渲染物体&#xff0c;引擎需要发出一个绘制调用来访问图形API&#xff08;iOS系统中为OpenGL ES&#xff09;。每个绘制调用需要进行大量的工作来访问图形API&#xff0c;从而导致了CPU方面显著的性能开销。Unity在运行时可以将一些物体进行合并&#xff0c;从而用一个…

第九十六期:JavaScript 中的 4 个相等比较算法的介绍

JavaScript 运算中&#xff0c;一共包含 4 个相等比较算法&#xff1a;抽象相等比较&#xff1b;严格相等比较&#xff1b;SameValueZero&#xff1b;SameValue。 作者&#xff1a;zhangbao90s JavaScript 运算中&#xff0c;一共包含 4 个相等比较算法&#xff1a; 抽象相等…

第九十七期:新版Kite:实时补全代码,Python之父都发声力挺!

不久前&#xff0c;一个免费的专门针对 Python 的代码补全工具 Kite&#xff0c;有了新的动态。 作者&#xff1a;杨鲤萍 本文转自雷锋网&#xff0c;如需转载请至雷锋网官网申请授权。 不久前&#xff0c;一个免费的专门针对 Python 的代码补全工具 Kite&#xff0c;有了新…

svn 版本升级的问题

原创文章&#xff0c;转载请注明 svn本地版本由1.6升级到1.7后&#xff0c;再使用时遇到一些问题&#xff0c;这里记录一下以备忘。 升级后&#xff0c;使用任何命令 不能用了&#xff0c;提示的意思大致是本地的workcopy版本太低了&#xff08;之前用1.6版本&#xff0c;check…

[JavaME]手机申请移动分配的动态IP(3)?

获取IP后是否可以和它通讯呢&#xff1f;<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />Hi&#xff0c;继续上回的讨论《[JavaME]手机是否能够申请到动态IP[2]?》。 上回说到申请动态IP是可以了&#xff0c;并且准备好了一个线…

第九十八期:TIOBE11月榜单:C、Swift、Go、D与Rust起起伏伏

TIOBE 指数并不代表语言的好坏&#xff0c;开发者可以使用该榜单检查自身的编程技能是否需要更新&#xff0c;或者在开始构建新软件时对某一语言做出选择。 作者&#xff1a;oschina TIOBE 公布了 11 月份编程语言排行榜。 本月前 20 名中有一些有趣的现象&#xff0c;先看看…

Vue 之 slot(插槽)

前言&#xff1a; vue中关于插槽的文档说明很短&#xff0c;语言又写的很凝练&#xff0c;再加上其和methods&#xff0c;data&#xff0c;computed等常用选项在使用频率、使用先后上的差别&#xff0c;这就有可能造成初次接触插槽的开发者容易产生“算了吧&#xff0c;回头再学…

第一百期:Java架构师:高并发下的流量控制

这个时候如果不做任何保护措施&#xff0c;服务器就会承受很大的处理压力&#xff0c;请求量很高&#xff0c;服务器负载也很高&#xff0c;并且当请求超过服务器承载极限的时候&#xff0c;系统就会崩溃&#xff0c;导致所有人都不能访问。 作者&#xff1a;IT技术分享 这个…

OpenCV学习笔记:矩阵的掩码操作

矩阵的掩码操作很简单。其思想是&#xff1a;根据掩码矩阵&#xff08;也称作核&#xff09;重新计算图像中每个像素的值。掩码矩阵中的值表示近邻像素值&#xff08;包括该像素自身的值&#xff09;对新像素值有多大影响。从数学观点看&#xff0c;我们用自己设置的权值&#…

spring mvc学习(15)Referenced file contains errors

SSM项目中出现Referenced file contains errors (http://www.springframework.org/schema/mvc/spring-mvc-3.0.xs 2019-01-20 22:37:06 薛定谔小猫Historia 阅读数 468更多 分类专栏&#xff1a; java及其框架学习 版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循…

spring mvc学习(16)Could not publish server configuration for Tomcat v8.0 Server at localhost.

这个问题本质是我们有多个重名项目&#xff0c;为什么我们会有多个重名项目&#xff0c;其实一般都是我们删除以前的项目&#xff0c;然后再把它重新导进eclipse时以前的项目删除不彻底造成的&#xff0c;以前的项目在"Servers"里面的"server.xml"文件下的…

产品管理:启示录 - 特约客户、产品验证、原型测试

• 如何挑选有潜力的产品&#xff1f; • 如何证明产品设计符合用户需求&#xff1f; • 如何确认产品设计满足三个基本条件&#xff1f; • 如何运用敏捷方法管理产品&#xff1f; • …… 这是《启示录》上说的一些话&#xff0c;去年看了一下&#xff0c;和团队分享了其中几…

37. Sudoku Solver

文章目录1 题目理解2 回溯1 题目理解 Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy all of the following rules: Each of the digits 1-9 must occur exactly once in each row. Each of the digits 1-9 must oc…