zoukankan      html  css  js  c++  java
  • Java多线程4:Thread中的静态方法

    一、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)

  • 相关阅读:
    matlab 函数库
    阿甘的珠宝 大数据博弈综合应用 SG函数 + 最后取为输或赢
    hdu 1536 博弈 SG函数(dfs)
    hdu 1907 John / 2509 Be the Winner 博弈 最后取完者为输
    深入理解 Nim 博弈
    SG函数模板 hdu 1848/1847/1849/1850/1851
    初始博弈 hdu 1846 Brave Game
    乘数密码 扩展欧几里得求逆元
    68.最大k乘积问题 (15分)
    第一次作业
  • 原文地址:https://www.cnblogs.com/zfyang2429/p/10520111.html
Copyright © 2011-2022 走看看