Java多线程技能-方法介绍

java 多线程技能

技术点:

  • 线程的启动
  • 如何使线程暂停
  • 如何使线程停止
  • 线程的优先级
  • 线程安全相关的问题

方法 currentThread()

currentThread() 方法可返回代码段正在被哪个线程调用。

public class MyThread extends Thread {

    public MyThread() {
        System.out.println("构造方法的打印:" + Thread.currentThread().getName());
    }

    @Override
    public void run() {
        System.out.println("run 方法的打印:" + Thread.currentThread().getName());
    }
}
public class Run {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start(); // 执行 run() 方法时机不确定时,启动新的线程
        //myThread.run(); // 立即执行 run() 方法,不启动新线程
    }
}

图示:image-20230222142407912.

方法 isAlive()

isAlive() 方法的功能是判断线程对象是否存活(测试线程是否处于活动状态)。

那什么是活动状态呢?

答:线程已经启动且尚未终止。如果线程处于正在运行或准备开始运行的状态,就认为线程是 “存活” 的。


注意:关键字 this 代表 this 所在类的对象。

public class CountOperate extends Thread {
    public CountOperate() {
        System.out.println("CountOperate---begin");
        System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
        System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
        System.out.println("this.getName()=" + this.getName());
        System.out.println("this.isAlive()=" + this.isAlive());
        System.out.println("CountOperate---end\n");
    }

    @Override
    public void run() {
        System.out.println("\nrun---begin");
        System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
        System.out.println("Thread.currentThread().isAlive()=" + Thread.currentThread().isAlive());
        System.out.println("this.getName()=" + this.getName());
        System.out.println("this.isAlive()=" + this.isAlive());
        System.out.println("run---end");
    }
}
public class Run {
    public static void main(String[] args) {
        CountOperate c = new CountOperate();
        Thread t1 = new Thread(c);
        System.out.println("main begin t1 isAlive=" + t1.isAlive());
        t1.setName("A");
        t1.start();
        System.out.println("main end t1 isAlive=" + t1.isAlive());
    }
}

图示:image-20230222145327900.

方法 sleep(long millis)

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

public class MyThread extends Thread {

    @Override
    public void run() {
        try {
            System.out.printf("run threadName=%s begin=%d\n", Thread.currentThread().getName(), System.currentTimeMillis());
            Thread.sleep(2000);
            System.out.printf("run threadName=%s end=%d\n", Thread.currentThread().getName(), System.currentTimeMillis());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
public class Run {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        System.out.printf("begin=%d\n", System.currentTimeMillis());
        myThread.start();
        System.out.printf("end=%d\n", System.currentTimeMillis());
    }
}

方法 sleep(long millis, int nanos)

public static void sleep(long millis, int nanos) 方法的作用是让当前正在执行的线程在指定的毫秒数加指定的纳秒数内休眠(暂停执行),此操作受到系统计时器及调度程序精度及准确性的影响。

public class Run {
    public static void main(String[] args) throws InterruptedException {
        long beginTime = System.currentTimeMillis();
        Thread.sleep(2000, 999999);
        long endTime = System.currentTimeMillis();
        System.out.println(endTime - beginTime);
    }
}

方法 StackTraceElement[] getStackTrace()

public StackTraceElement[] getStackTrace() 方法的作用是返回一个表示该线程的堆栈跟踪元素数组。如果该线程尚未启动或已经终止,则该方法将返回一个零长度数组。如果返回的数组不是零长度的,则其第一个元素代表堆栈顶,它是该数组中最新的方法调用。最后一个元素代表堆栈底,是该数组中最旧的方法调用。

public class Run {
    public static void main(String[] args) {
        new Run().a();
    }

    public void a() {
        b();
    }

    private void b() {
        c();
    }

    private void c() {
        d();
    }

    private void d() {
        e();
    }

    private void e() {
        StackTraceElement[] array = Thread.currentThread().getStackTrace();
        for (int i = 0; i < array.length; i++) {
            StackTraceElement eachElement = array[i];
            System.out.printf("className=%s methodName=%s fileName=%s lineNumber=%s\n",
                    eachElement.getClassName(), eachElement.getMethodName(), eachElement.getFileName(), eachElement.getLineNumber());
        }
    }
}

图示:image-20230222175610145.

方法 static void dumpStack()

public static void dumpStack() 方法的作用是将当前线程的堆栈信息输出至标准错误流。该方法仅用于调试。

public class Run {
    public static void main(String[] args) {
        new Run().a();
    }

    public void a() {
        b();
    }

    private void b() {
        c();
    }

    private void c() {
        d();
    }

    private void d() {
        e();
    }

    private void e() {
        int age = 0;
        age = 100;
        if (age == 100) {
            Thread.dumpStack();
        }
    }
}

图示:image-20230222180131670.

方法 Map<Thread, StackTraceElement[]> getAllStackTraces()

Map<Thread, StackTraceElement[]> getAllStackTraces() 方法的作用是返回所有活动线程的堆栈信息的一个映射。Map 的 key 是线程对象,而 Map 的 value 是一个 StackTraceElement 数组,该数组表示相应 Thread 的堆栈信息。在调用该方法的同时,线程可能也在执行。每个线程的堆栈信息仅代表线程当时状态的一个快照。

public class Run {
    public static void main(String[] args) {
        new Run().a();
    }

    public void a() {
        b();
    }

    private void b() {
        c();
    }

    private void c() {
        d();
    }

    private void d() {
        e();
    }

    private void e() {
        Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
        if (map.size() != 0) {
            Iterator<Thread> keyIterator = map.keySet().iterator();
            while (keyIterator.hasNext()) {
                Thread eachThread = keyIterator.next();
                StackTraceElement[] array = map.get(eachThread);
                System.out.println("------每个线程的基本信息");
                System.out.println("\t线程名称:" + eachThread.getName());
                System.out.println("StackTraceElement[].length=" + array.length);
                System.out.println("\t线程状态:" + eachThread.getState());
                if (array.length != 0) {
                    System.out.println("\t打印 StackTraceElement[] 数组具体信息:");
                    for (int i = 0; i < array.length; i++) {
                        StackTraceElement eachElement = array[i];
                        System.out.println("\t" + eachElement.getClassName() + " "
                                + eachElement.getMethodName() + " " + eachElement.getFileName() + " "
                                + eachElement.getLineNumber());
                    }
                } else {
                    System.out.println("\t没有 StackTraceElement[] 信息,因为线程" + eachThread.getName() 
                            + " 中的 StackTraceElement[].length==0");
                }
                System.out.println();
                System.out.println();
            }
        }
    }
}

图示:image-20230222194831606.

方法 getId()

getId() 方法可以取得线程的唯一数字标识。

public class Run {
    public static void main(String[] args) {
        Thread runThread = Thread.currentThread();
        System.out.println(runThread.getName() + " " + runThread.getId());
        Thread t1 = new Thread();
        System.out.println(t1.getName() + " " + t1.getId());
        Thread t2 = new Thread();
        System.out.println(t2.getName() + " " + t2.getId());
        Thread t3 = new Thread();
        System.out.println(t3.getName() + " " + t3.getId());
    }
}

图示:image-20230222195306999.

从运行结果来看,当前执行代码的线程名为 main,线程 id 值为 1。

而 Thread-0 线程的 id 值直接到达 20,说明中间有 18 个id 值被隐藏的线程占有。

posted @ 2023-02-22 20:00  软柠柠吖  阅读(10)  评论(0编辑  收藏  举报