博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java多线程4:Thread中的静态方法
阅读量:5039 次
发布时间:2019-06-12

本文共 8322 字,大约阅读时间需要 27 分钟。

一、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构造函数的打印:mainrun方法的打印: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构造函数中通过静态方法调用:mainrun方法中通过this调用:Thread-0run方法中通过静态方法调用: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 * interrupted status 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 开始===1552401515206main 结束=====1552401515208run 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.     *     * 

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. * *

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
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 的时长为:0msi = 49    第49次yield 的时长为:0msi = 50    第50次yield 的时长为:1msi = 51    第51次yield 的时长为:0msi = 52    第52次yield 的时长为:4msi = 53    第53次yield 的时长为:0msi = 54    第54次yield 的时长为:0ms..............................................................................i = 442    第442次yield 的时长为:0msi = 443    第443次yield 的时长为:0msi = 444    第444次yield 的时长为:1msi = 445    第445次yield 的时长为:0msi = 446    第446次yield 的时长为:0ms..............................................................................

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

  4、interrupted()

/**     * Tests whether the current thread has been interrupted.  The     * interrupted status 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).     *     * 

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 true if the current thread has been interrupted; * false 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线程是否被中断?truemain线程是否被中断?false

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

 

参考资料:

  

  

转载于:https://www.cnblogs.com/zfyang2429/p/10520111.html

你可能感兴趣的文章
python将两个数组合并成一个数组的两种方法的代码
查看>>
Java基础8-浅谈java程序的运行机制与JVM运行
查看>>
MyBatis之级联——鉴别器
查看>>
javascript:void(0)的含义
查看>>
解决android启动程序时,会出现一个短暂的白色空白界面的问题
查看>>
BZOJ‘s Usaco 奶牛题集锦
查看>>
生成器
查看>>
drf权限组件
查看>>
输入月份和日期,得出是今年第几天
查看>>
利用mysqldump备份mysql
查看>>
Qt中子窗口全屏显示与退出全屏
查看>>
使用brew安装软件
查看>>
[BZOJ1083] [SCOI2005] 繁忙的都市 (kruskal)
查看>>
吴裕雄 python 机器学习——数据预处理嵌入式特征选择
查看>>
Centos6.4安装JDK
查看>>
201521123069 《Java程序设计》 第4周学习总结
查看>>
线性表的顺序存储——线性表的本质和操作
查看>>
【linux】重置fedora root密码
查看>>
数组的扩展
查看>>
关于空间背景颜色的操作
查看>>