一、Thread类中的静态方法

  Thread类中的静态方法是通过Thread.方法名来调用的,那么问题来了,这个Thread指的是哪个Thread,是所在位置对应的那个Thread嘛?通过下面的例子可以知道,Thread类中的静态方法所操作的线程是“正在执行该静态方法的线程”,不一定是其所在位置的线程。为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程进行操作。下面来看一下Thread类中的静态方法:

  1、currentThread()

/**
* Returns a reference to the currently executing thread object.
*
* @return the currently executing thread.
*/
public static native Thread currentThread();

  currentThread()方法返回的是对当前正在执行的线程对象的引用

  举例:

public class Thread01 extends Thread{

    static{
System.out.println("静态代码块的打印:" + Thread.currentThread().getName());
} public Thread01(){
System.out.println("构造函数的打印:" +Thread.currentThread().getName());
} @Override
public void run() {
System.out.println("run方法的打印:" + Thread.currentThread().getName());
}
}
public class Test {
public static void main(String[] args){
Thread01 thread01 = new Thread01();
thread01.start();
}
}

  结果:

静态代码块的打印:main
构造函数的打印:main
run方法的打印:Thread-0

  可以看到,Thread01类中的三个相同的静态方法Thread.currentThread()所操作的不是同一个线程,虽然写在了Thread01内,但是静态代码块和构造函数中的静态方法是随着main线程而被调用的,run方法中的静态方法则是thread01线程调用的。把thread01.start()注释掉

public class Test {
public static void main(String[] args){
Thread01 thread01 = new Thread01();
// thread01.start();
}
}

  结果:

静态代码块的打印:main
构造函数的打印:main

  因为Thread01中的静态代码块和构造方法都是在main线程中被调用的,而run方法是thread01这个线程调用的,所以不一样。

  举例说明上篇说的"this.XXX()"和"Thread.currentThread().XXX()"的区别,this表示的线程是线程实例本身,后一种表示的线程是正在执行"Thread.currentThread.XXX()这块代码的线程"

public class Thread01 extends Thread{

    public Thread01(){
System.out.println("构造函数中通过this调用:" + this.getName());
System.out.println("构造函数中通过静态方法调用:" + Thread.currentThread().getName());
} @Override
public void run() {
System.out.println("run方法中通过this调用:" + this.getName());
System.out.println("run方法中通过静态方法调用:" + Thread.currentThread().getName());
}
}
public class Test {
public static void main(String[] args){
Thread01 thread01 = new Thread01();
thread01.start();
}
}

  结果:

构造函数中通过this调用:Thread-0
构造函数中通过静态方法调用:main
run方法中通过this调用:Thread-0
run方法中通过静态方法调用:Thread-0

  同样的,把thread01.start()这一行注释掉以后

public class Test {
public static void main(String[] args){
Thread01 thread01 = new Thread01();
// thread01.start();
}
}

  结果:

构造函数中通过this调用:Thread-0
构造函数中通过静态方法调用:main

  所以,在Thread01里面通过Thread.currentThread得到的线程对象的引用不一定就是Thread01,要看该方法所在的代码会被哪个线程调用。

  2、sleep(long millis)

/**
* Causes the currently executing thread to sleep (temporarily cease
* execution) for the specified number of milliseconds, subject to
* the precision and accuracy of system timers and schedulers. The thread
* does not lose ownership of any monitors.
*
* @param millis
* the length of time to sleep in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public static native void sleep(long millis) throws InterruptedException;

  sleep(long millis)方法的作用是在指定的毫秒内让当前"正在执行的线程"休眠(暂停执行)。这个"正在执行的线程"是关键,指的是Thread.currentThread()返回的线程。根据JDK API的说法,"该线程不丢失任何监视器的所属权",简单说就是sleep代码上下文如果被加锁了,锁依然在,但是CPU资源会让出给其他线程。

  举例:

public class Thread01 extends Thread{

    @Override
public void run() {
try {
System.out.println("run threadName:" + this.getName());
System.out.println("调用Thread.sleep方法休眠3秒");
Thread.sleep(3000);
System.out.println("run threadName:" + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args){
System.out.println("main 开始===" + System.currentTimeMillis());
Thread01 thread01 = new Thread01();
thread01.start();
System.out.println("main 结束=====" + System.currentTimeMillis());
}
}

  结果:

main 开始===1552401515206
main 结束=====1552401515208
run threadName:Thread-0
调用Thread.sleep方法休眠3秒
run threadName:Thread-0

  3、yield()

/**
* A hint to the scheduler that the current thread is willing to yield
* its current use of a processor. The scheduler is free to ignore this
* hint.
*
* <p> Yield is a heuristic attempt to improve relative progression
* between threads that would otherwise over-utilise a CPU. Its use
* should be combined with detailed profiling and benchmarking to
* ensure that it actually has the desired effect.
*
* <p> It is rarely appropriate to use this method. It may be useful
* for debugging or testing purposes, where it may help to reproduce
* bugs due to race conditions. It may also be useful when designing
* concurrency control constructs such as the ones in the
* {@link java.util.concurrent.locks} package.
*/
public static native void yield();

  暂停当前执行的线程,并执行其他的线程。这个暂停是会放弃CPU资源的,并且放弃CPU的时间不确定,有可能刚放弃,就获得CPU资源了,也有可能放弃好一会儿,才会被CPU执行。

  举例说明yield()放弃CPU的时间是不一定的,用户无法指定

public class Thread01 extends Thread{
@Override
public void run() {
for(int i = 1; i <= 500; i++) {
long beginTime = System.currentTimeMillis();
Thread.yield();
long endTime = System.currentTimeMillis();
System.out.println(" 第" + i + "次yield 的时长为:" + (endTime - beginTime) + "ms");
System.out.println("i = " + i);
}
}
}
public class Thread02 extends Thread{
@Override
public void run() {
for(int i = 0; i < 500000; i++) {
List<Integer> list = new ArrayList<>();
list.add(i);
}
}
}
public class Test {
public static void main(String[] args) {
Thread01 thread01 = new Thread01();
thread01.start();
//根据Thread02多开几个线程
Thread02 thread02 = new Thread02();
thread02.start();
Thread02 thread021 = new Thread02();
thread021.start();
Thread02 thread022 = new Thread02();
thread022.start();
Thread02 thread023 = new Thread02();
thread023.start();
Thread02 thread024 = new Thread02();
thread024.start();
}
}

  结果:

.......................................
.......................................
i = 48
第48次yield 的时长为:0ms
i = 49
第49次yield 的时长为:0ms
i = 50
第50次yield 的时长为:1ms
i = 51
第51次yield 的时长为:0ms
i = 52
第52次yield 的时长为:4ms
i = 53
第53次yield 的时长为:0ms
i = 54
第54次yield 的时长为:0ms
.......................................
.......................................
i = 442
第442次yield 的时长为:0ms
i = 443
第443次yield 的时长为:0ms
i = 444
第444次yield 的时长为:1ms
i = 445
第445次yield 的时长为:0ms
i = 446
第446次yield 的时长为:0ms
.......................................
.......................................

  可以看到,yield()方法放弃CPU的时间是不确定的,可能立马就被CPU执行,也可能要等待一会再被CPU执行。

  4、interrupted()

/**
* Tests whether the current thread has been interrupted. The
* <i>interrupted status</i> of the thread is cleared by this method. In
* other words, if this method were to be called twice in succession, the
* second call would return false (unless the current thread were
* interrupted again, after the first call had cleared its interrupted
* status and before the second call had examined it).
*
* <p>A thread interruption ignored because a thread was not alive
* at the time of the interrupt will be reflected by this method
* returning false.
*
* @return <code>true</code> if the current thread has been interrupted;
* <code>false</code> otherwise.
* @see #isInterrupted()
* @revised 6.0
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}

  测试当前线程是否处于中断状态,调用该方法,线程中断状态的标识被清除(置为false),也就是说,如果这个方法被连续调用两次,第二次一定会返回false

public class Test {
public static void main(String[] args) {
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().getName() + "线程是否被中断?" + Thread.interrupted());
System.out.println(Thread.currentThread().getName() + "线程是否被中断?" + Thread.interrupted());
}
}

  结果:

main线程是否被中断?true
main线程是否被中断?false

  当然,这也涉及Java的中断机制,留在后面的一篇文章专门讲解。

参考资料:

  Java多线程3:Thread中的静态方法

  Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)

Java多线程4:Thread中的静态方法的更多相关文章

  1. java 多线程 2 Thread中start()和run()的区别

  2. Java多线程3:Thread中的静态方法

    Thread类中的静态方法 Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程".为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程 ...

  3. Java多线程01(Thread类、线程创建、线程池)

    Java多线程(Thread类.线程创建.线程池) 第一章 多线程 1.1 多线程介绍 1.1.1 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于 ...

  4. JAVA多线程(一) Thread & Runnable

    githut代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-service/ ...

  5. java多线程创建-Thread,Runnable,callable和threadpool

    java创建多线程的方式有许多种,这里简要做个梳理 1. 继承Thread类 继承java.lang.Thread类,创建本地多线程的类,重载run()方法,调用Thread的方法启动线程.示例代码如 ...

  6. Java 多线程(1)-Thread和Runnable

    一提到Java多线程,首先想到的是Thread继承和Runnable的接口实现 Thread继承 public class MyThread extends Thread { public void ...

  7. Java 多线程 (Thread 类)

    1.多线程 2.卖票 1.多线程实现 两种方式可以实现多线程: 继承 Thread 类,重写 run 方法:定义对象,调用 start 方法 创建类实现 Runnable 接口,作为实参传递给 thr ...

  8. Java 多线程之 Thread 类 和 Runnable 接口初步使用

    目录 Thread 类 Thread之定义线程类 Thread之开启线程 Runnable 接口 Runnable 之定义线程类 Runnable 之开启线程 @ Thread 类 Thread 类是 ...

  9. Java 多线程查找文件中的内容

    学过了操作系统,突然不知道多线程有什么用了. 看了一下百度,发现多线程,可以提升系统利用率 在系统进行IO操作的时候,CPU可以处理一些其他的东西,等IO读取到内存后,CPU再处理之前的操作. 总之可 ...

随机推荐

  1. [SDOi2012]吊灯

    嘟嘟嘟 这题想了半天,搞出了一个\(O(10 * d * n)\)(\(d\)为\(n\)的约数个数)的贪心算法,就是能在子树内匹配就在子树内匹配,否则把没匹配的都交给父亲,看父亲能否匹配.交上去开了 ...

  2. LeetCode练习2 两数相加

    问题如下: 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来 ...

  3. 009_npm常用命令参数总结

    npm是什么 NPM的全称是Node Package Manager,是随同NodeJS一起安装的包管理和分发工具,它很方便让JavaScript开发者下载.安装.上传以及管理已经安装的包. 一.np ...

  4. (二 -3-1) 天猫精灵接入Home Assistant-自动发现Mqtt设备--灯系列 实战

    #本片教程介绍了具体如何实现天猫精灵控制一个灯. 前提: HASS平台 你已经搭建一个可以在公网IP访问到的HASS平台--- 我用的是租了阿里云服务器,买了个域名,ubuntu1604系统 你已经搭 ...

  5. python+selenium基础之XPATH轴定位(第二篇)

    第一篇讲了xpath定位的一些基本定位方法,这里再介绍一种:xpath轴定位,应用场景是当某个元素的各个属性及其组合都不足以定位时,那么可以利用其兄弟节点或者父节点等各种可以定位的元素进行定位. 1. ...

  6. SkylineGlobe 7.0版本 矢量数据查询示例代码

    在Pro7.0.0和7.0.1环境下测试可用. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...

  7. Spring Boot 之使用 Json 详解

    Spring Boot 之使用 Json 详解 简介 Spring Boot 支持的 Json 库 Spring Web 中的序列化.反序列化 指定类的 Json 序列化.反序列化 @JsonTest ...

  8. JUnit5 快速指南

    JUnit5 快速指南 version: junit5 1. 安装 2. JUnit 注解 3. 编写单元测试 3.1. 基本的单元测试类和方法 3.2. 定制测试类和方法的显示名称 3.3. 断言( ...

  9. 对写博客的n种思考

    喜欢才能坚持 开始写博客的原因非常功利,功利到不好意思说. 反正你们也懂的,就那么几种. 问题是,如果心态一直这么功利,而写博客的前期回报几乎为零,情绪会变得沮丧,不知如何继续. 不过后来想想,其实做 ...

  10. Django 多表查询练习题 Q查询 F查询 聚合 分组

    -------------------------------------------------自己偷的懒,或许用加倍时间也补不回来,珍惜现在的拥有的时光,把我现在! 上节回顾 基于对象的跨表查询( ...