Java多线程系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线程的深入剖析。

多线程的常用方法

1、currentThread()方法:

介绍:currentThread()方法可返回该代码正在被哪个线程调用的信息。

示例

例1:

public class Test01 {public static void main(String[] args) {System.out.println(Thread.currentThread().getName());}}结果:
main

结果说明,main方法被名为main的线程调用

例2:

class Mythread extends Thread{public Mythread() {System.out.println("构造方法的打印:"+Thread.currentThread().getName());}@Overridepublic void run() {System.out.println("run方法的打印:"+Thread.currentThread().getName());}
}public class Test01 {public static void main(String[] args) {Mythread t=new Mythread();t.start();//①}}结果:
构造方法的打印:main
run方法的打印:Thread-0

从结果可知:Mythread的构造方法是被main线程调用的,而run方法是被名称为Thread-0的线程调用的,run方法是线程自动调用的

现在我们将①处的代码改为t.run(),现在的输出结果如下:

构造方法的打印:main
run方法的打印:main

从结果中我们可以看到两次的结果显示都是main线程调用了方法,因为当你使用t.start()方法的时候是线程自动调用的run()方法,所以输出的是Thread-0,当你直接调用run()方法时,和调用普通方法没有什么区别,所以是main线程调用run()

2、isAlive()方法:

介绍:isAlive()方法的功能是判断当前的线程是否处于活动状态

示例:

例1:

class Mythread extends Thread{@Overridepublic void run() {System.out.println("run =="+this.isAlive());}}public class Test01 {public static void main(String[] args) {Mythread thread=new Mythread();System.out.println("begin =="+thread.isAlive());//①thread.start();//②System.out.println("end =="+thread.isAlive());//③}}结果:
begin ==false
end ==true
run ==true

方法isAlive()的作用是测试线程是否处于活动状态。那么什么情况下是活动状态呢?活动状态就是线程已经启动且尚未停止。线程处于正在运行或准备开始运行的状态,就认为线程是存活的

①处代码的结果为false,因为此时线程还未启动;

②处代码调用了run()方法输出结果为run ==true,此时线程处于活动状态;

③处代码的结果为true,有的同学看到这个输出可能会不理解,不是说线程处于活动状态isAlive()方法的结果才是true,现在程序都已经运行结束了为什么还是true?这里的输出结果是不确定的,我们再来看下面一段代码

我们将例1中的代码稍做修改,代码如下:

public class Test01 {public static void main(String[] args) throws InterruptedException {Mythread thread=new Mythread();System.out.println("begin =="+thread.isAlive());//①thread.start();//②Thread.sleep(1000);//这里加了一行代码,让当前线程沉睡1秒System.out.println("end =="+thread.isAlive());//③}}结果:
begin ==false
run ==true
end ==false

现在我们看到③处的代码结果为end ==false,因为thread对象已经在1秒内执行完毕,而上面代码输出结果为true是因为thread线程未执行完毕。

3、sleep()方法:

介绍:

方法sleep()的作用是在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行),这个“正在执行的线程”是指this.currentThread()返回的线程。

示例:

class Mythread extends Thread{@Overridepublic void run() {try {System.out.println("run threadName="+this.currentThread().getName()+" begin");Thread.sleep(2000);System.out.println("run threadName="+this.currentThread().getName()+" end");} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}public class Test01 {public static void main(String[] args) throws InterruptedException {Mythread thread=new Mythread();System.out.println("begin ="+System.currentTimeMillis());thread.run();//①System.out.println("end ="+System.currentTimeMillis());}}结果:
begin =1574660731663
run threadName=main begin
run threadName=main end
end =1574660733665

从结果中可以看出main线程暂停了2秒(因为这里调用的是thread.run())

下面我们将①处的代码改成thread.start(),再来看下运行结果:

begin =1574661491412
end =1574661491412
run threadName=Thread-0 begin
run threadName=Thread-0 end

由于main线程与thread线程是异步执行的,所以首先打印的信息为begin和end,而thread线程是随后运行的,在最后两行打印run begin和run end的信息。

4、getId()方法:

介绍:getId()方法的作用是取得线程的唯一标识

示例

public class Test01 {public static void main(String[] args) throws InterruptedException {Thread thread=Thread.currentThread();System.out.println(thread.getName()+" "+thread.getId());}}

结果:main 1

从运行结果可以看出,当前执行代码的线程名称是main,线程id值为1

5、停止线程:

介绍:停止线程是在多线程开发时很重要的技术点,掌握此技术可以对线程的停止进行有效的处理。停止线程在Java语言中并不像break语句那样干脆,需要一些技巧性的处理。

在java中有三种方法可以停止线程

  1. 使用退出标志,让线程正常退出,也就是当run方法执行完之后终止
  2. 使用stop方法强制终止线程,但是不推荐使用,因为stop和suspend及resume一样,是java废弃的方法
  3. 使用interrupt方法中断线程(推荐使用)

示例:

例1:

class Mythread extends Thread{@Overridepublic void run() {for(int i=0;i<5000;i++) {System.out.println("i="+(i+1));}}}public class Test01 {public static void main(String[] args) throws InterruptedException {Mythread thread=new Mythread();thread.start();Thread.sleep(2000);thread.interrupt();}}

运行结果:

从运行结果我们可以看出最后i=500000,调用interrupt方法没有停止线程,那么该如何停止线程呢?

在介绍如何停止线程时,我们先来介绍一下如何判断线程是否处于停止状态

Thread类中提供了两种方法用来判断线程是否停止:

1、this.interrupted():测试当前线程是否已经中断,执行后具有将状态标志清除为false的功能

public static boolean interrupted() {return currentThread().isInterrupted(true);
}

2、this.isInterrupted():测试线程Thread对象是否已经中断,但是不清除状态标志

public boolean isInterrupted() {return isInterrupted(false);
}

读者可以仔细观看一下这两个方法的声明有什么不同?

例2:

class Mythread extends Thread{@Overridepublic void run() {for(int i=0;i<5000;i++) {System.out.println("i="+(i+1));}}}public class Test01 {public static void main(String[] args) throws InterruptedException {Mythread thread=new Mythread();thread.start();Thread.sleep(1000);thread.interrupt();System.out.println("是否停止1?="+thread.interrupted());System.out.println("是否停止2?="+thread.interrupted());System.out.println("end!");}}

结果:

输出结果显示调用了thread.interrupt()方法后线程并未停止,这也就证明了interrupted()方法的解释:测试当前线程是否已经中断。这个当前线程是main,它从未断过,所以打印的结果是两个false。

如果想让main线程结束该怎么做?

将main方法改成如下:

public class Test01 {public static void main(String[] args) throws InterruptedException {Thread.currentThread().interrupt();System.out.println("是否停止1?="+Thread.interrupted());System.out.println("是否停止2?="+Thread.interrupted());System.out.println("end!");}}结果:
是否停止1?=true
是否停止2?=false
end!

从输出结果我们可以看出,方法interrupted()的确判断出当前线程是否是停止状态。但为什么第2个值是false?

查看一下官方文档的介绍:

测试当前线程是否已经中断。线程的中断状态由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。

文档中说明的非常清楚,interrupted()方法具有清除状态的功能,所以第二次调用interrupted方法返回的值时false。

下面我们来看一下isInterrupted()方法,将main方法改成如下代码:

public static void main(String[] args) throws InterruptedException {Mythread thread=new Mythread();thread.start();thread.interrupt();Thread.sleep(1000);System.out.println("是否停止1?="+thread.isInterrupted());System.out.println("是否停止2?="+thread.isInterrupted());System.out.println("end");
}结果:

是否停止1?=true是否停止2?=trueend

从结果可以看出,方法isInterrrupted()并未清除状态,所以结果为两个true。

例3:在沉睡中停止

当线程调用sleep()方法后再调用interrupt()方法后会有什么结果:

class Mythread extends Thread{@Overridepublic void run() {try {System.out.println("run begin");Thread.sleep(200000);System.out.println("run end");} catch (InterruptedException e) {System.out.println("在沉睡中被停止,进入catch!"+this.isInterrupted());e.printStackTrace();}}}public class Test01 {public static void main(String[] args) throws InterruptedException {try {Mythread thread=new Mythread();thread.start();Thread.sleep(200);thread.interrupt();}catch(Exception e) {System.out.println("main catch");e.printStackTrace();}System.out.println("end!");}}

6、暂停线程:

暂停线程意味着此线程还可以恢复运行。在java多线程中,可以使用suspend()方法暂停线程,使用resume()方法恢复线程的执行

例1:

class Mythread extends Thread{private long i=0;public long getI() {return i;}public void setI(long i) {this.i = i;}@Overridepublic void run() {while(true) {i++;}}}public class Test01 {public static void main(String[] args) throws InterruptedException {Mythread thread=new Mythread();thread.start();Thread.sleep(5000);//A段thread.suspend();System.out.println("A= "+System.currentTimeMillis()+" i="+thread.getI());Thread.sleep(5000);System.out.println("A= "+System.currentTimeMillis()+" i="+thread.getI());//B段thread.resume();Thread.sleep(5000);//C段thread.suspend();System.out.println("B= "+System.currentTimeMillis()+" i="+thread.getI());Thread.sleep(5000);System.out.println("B= "+System.currentTimeMillis()+" i="+thread.getI());}}

结果:

从控制台打印的时间上来看,线程的确被暂停了,而且还可以恢复成运行状态。

7、yield方法:

介绍:yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片

示例:

class Mythread extends Thread{@Overridepublic void run() {long beginTime=System.currentTimeMillis();int count=0;for(int i=0;i<500000;i++) {               //Thread.yield();①count=count+(i+1);}long endTime=System.currentTimeMillis();System.out.println("用时:"+(endTime-beginTime)+"毫秒!");}}public class Test01 {public static void main(String[] args) throws InterruptedException {Mythread thread=new Mythread();thread.start();}}

结果:用时:2毫秒!

现在将①处的代码取消注释,我们再来看一下运行结果:

用时:213毫秒!

将CPU让给其他资源导致速度变慢

8、线程优先级:

介绍:

在操作系统中,线程可以划分优先级,优先级较高的线程得到的CPU资源较多,也就是CPU优先执行优先级较高的线程对象中的任务。

设置线程优先级有助于帮“线程规划器”确定在下一次选择哪一个线程来优先执行。

设置线程的优先级使用setPriority()方法,此方法在JDK的源代码如下:

public final void setPriority(int newPriority) {ThreadGroup g;checkAccess();if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {throw new IllegalArgumentException();}if((g = getThreadGroup()) != null) {if (newPriority > g.getMaxPriority()) {newPriority = g.getMaxPriority();}setPriority0(priority = newPriority);}
}

在Java中,线程的优先级为1-10这10个等级,如果小于1或大于10,则JDK抛出异常throw new IllegalArgumentException()。

通常高优先级的线程总是先执行完,但是并不是一定的,高优先级和低优先级的线程会交替进行,高优先级执行的次数多一些

线程优先级的继承特性:

在Java中,线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级与A是一样的。

class Mythread2 extends Thread{@Overridepublic void run() {System.out.println("Mythread2 run priority="+this.getPriority());}
}class Mythread1 extends Thread{@Overridepublic void run() {System.out.println("Mythread run priority="+this.getPriority());Mythread2 thread2=new Mythread2();thread2.start();}}public class Test01 {public static void main(String[] args) throws InterruptedException {System.out.println("main thread begin priority="+Thread.currentThread().getPriority());//Thread.currentThread().setPriority(6);①System.out.println("main thread end priority="+Thread.currentThread().getPriority());Mythread1 thread1=new Mythread1();thread1.start();}}结果:
main thread begin priority=5
main thread end priority=5
Mythread run priority=5
Mythread2 run priority=5

可以看到上面几个线程的优先级都为5

现在将①处的代码注释掉后的结果是:

main thread begin priority=5
main thread end priority=6
Mythread run priority=6
Mythread2 run priority=6

优先级被更改后再继续继承

9、守护线程:

在java中有两种线程,一种是用户线程,另一种是守护线程。

守护线程是一种特殊的线程,它的特性有“陪伴”的含义,当进程中不存在非守护线程了,则守护线程自动销毁。典型的守护线程就是垃圾回收线程,当进程中没有非守护线程了,则垃圾回收线程也就没有存在的必要了,自动销毁。用个比较通俗的比喻来解释一下:“守护线程”:任何一个守护线程都是整个JVM中所有非守护线程的“保姆”,只要当前JVM实例中存在任何一个非守护线程没有结束,守护线程就在工作,只有当最后一个非守护线程结束时,守护线程才随着JVM一同结束工作。Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是GC(垃圾回收器),它就是一个很称职的守护者。

class Mythread extends Thread{private int i=0;@Overridepublic void run() {try {while(true) {i++;System.out.println("i="+(i));Thread.sleep(1000);}}catch(Exception e) {e.printStackTrace();}}}public class Test01 {public static void main(String[] args) throws InterruptedException {try {Mythread thread=new Mythread();thread.setDaemon(true);thread.start();Thread.sleep(5000);System.out.println("我离开Thread对象就不再打印了,也就是停止了");}catch(Exception e) {e.printStackTrace();}}}

Java——多线程之方法详解相关推荐

  1. JAVA 多线程并发超详解

    JAVA 多线程并发超详解(未完,下一篇文章还有) 1. JAVA 多线程并发 1.1.1. JAVA 并发知识库 1.1.2. JAVA 线程实现/创建方式 1.1.2.1. 继承 Thread 类 ...

  2. Java之toString()方法详解

    Java之toString()方法详解 Java中 toString()方法在Object类中和Intent类中都有定义,作用类似,但显示形式有点区别 一.Object类中toString()方法 t ...

  3. Java 静态工厂方法详解

    Java 静态工厂方法详解 本文章主要是对<Effective Java>对静态工厂方法的理解 第一次使用静态工厂方法是在HIT<Software Construction>课 ...

  4. java 多线程同步_详解Java多线程编程中的线程同步方法

    1.多线程的同步: 1.1.同步机制:在多线程中,可能有多个线程试图访问一个有限的资源,必须预防这种情况的发生.所以引入了同步机制:在线程使用一个资源时为其加锁,这样其他的线程便不能访问那个资源了,直 ...

  5. Java多线程(超详解)

    目录 1. 线程简介 1.1 程序 1.2 进程 1.3 线程 1.4 多线程 1.5 普通方法调用和多线程 2. 线程创建 2.1 继承Thread类 2.2 实现Runnable接口 2.3 实现 ...

  6. java 多线程基础 万字详解(通俗易懂)

    目录 一.前言 二.定义 1.进程 : 2.线程 : 3.单线程与多线程 : 4.并发与并行 : 三.线程的创建 1.创建线程的两种基本方式 : 1° 继承Thread类,并重写run方法 1.5° ...

  7. Java多线程:类ThreadPoolExecutor详解

    为什么80%的码农都做不了架构师?>>>    1 public ThreadPoolExecutor(int corePoolSize, 2                     ...

  8. Java Arrays.asList()方法详解

    本文是对Arrays.asList()方法从源码角度进行分析,解析使用中的一些困惑. 首先看Arrays.asList()的源码 public static <T> List<T&g ...

  9. java的intern()方法详解

    尽管在输出中调用intern方法并没有什么效果,但是实际上后台这个方法会做一系列的动作和操作.在调用"ab".intern()方法的时候会返回"ab",但是这个 ...

最新文章

  1. 谷歌排名第一的编程语言,死磕它这两点,小白也能学的会!不信你看!
  2. python使用matplotlib可视化雷达图(polar函数可视化雷达图、极坐标图、通过径向方向来显示数据之间的关系)
  3. 姚班、智班之后,量子信息班在清华成立,姚期智担纲,“致力国家战略需求”!...
  4. jenkins的基本操作
  5. python 第一课
  6. java ==和===_java中==和equals的区别详解
  7. 太监式的自主知识产权研发特色 (Z)
  8. Arduino 端口通信实例
  9. how to reference the parent form from the WPF control(Control in ElementHost)
  10. 一个Linux驱动:Simple - REALLY simple memory mapping demonstration.
  11. TypeError: __str__ returned non-string (type NoneType)
  12. aode matlab程序,三大计算机视觉和机器学习库的算法汇总
  13. 短消息代理(cmpp20 smproxy)要怎么创建java项目_基于华为smproxy开发的cmpp3
  14. MYSQL-Front新手连接数据库总结
  15. QT读取局域网共享文件夹文件内容 解决不同网段无法访问共享文件夹问题
  16. Eclipse 启动提示java虚拟机启动失败,“Failed to create the Java Virtual Machine”-------解决方法
  17. 海康威视摄像头连接(.net)
  18. vue html 格式化,解决在写Vue时,格式化代码 属性自动换行的问题
  19. java script中extends,JavaScript继承之ES6的extends
  20. gcrobustvar:基于VAR的稳健性Granger因果检验

热门文章

  1. 互联网摸鱼日报(2022-10-07)
  2. 北工大计算机学院博导,北工大计算机学院计算机科学与技术导师介绍:李玉鉴...
  3. gdb调试出现“Could not insert hardware watchpoint”
  4. 新标签页打开链接_显示空白的问题!
  5. 机器学习基础-11:机器学习的分类
  6. idea目录结构各种修改
  7. 我的Java开发生涯记(14)
  8. 电源空间辐射CDN余量低_史上最全开关电源传导与辐射超标整改方案
  9. 使用selenium爬取Virustotal
  10. 【转】和蜗牛一起学DIRECTOR 第二讲 按钮效果