线程的常用方法


1.1 currentThread()方法(类方法)

         Thread.currentThread()方法可以获得当前线程

         Java 中的任何一段代码都是执行在某个线程当中的.。执行当前代 码的线程就是当前线程。

         同一段代码可能被不同的线程执行, 因此当前线程是相对 的,Thread.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 Test {

    public static void main(String[] args) {

        System.out.println("main 方 法 中 打 印 当 前 线 程 :"         
       +Thread.currentThread().getName());

        //创建子线程, 调用 MyThead()构造方法, 在 main 线程中调用构造方法,所以构造
        //方法中 的当前线程就是 main 线程
        MyThread t1 = new MyThread();

         t1.start(); //启动子线程,子线程会调用 run()方法,所以 run()方法中 的当
        //前线程就是 Thread-0 子线程
       
    }
}

结果: 

     

java Forkjoin 线程中打印traceId java 打印当前线程_多线程

 

结论:

        创建子线程, 调用 MyThead()构造方法, 在 main 线程中调用构造方法,所以构造方法中 的当前线程就是 main 线程

        启动子线程,子线程会调用 run()方法,所以 run()方法中 的当前线程就是 Thread-0 子线程


1.2  setName()/getName()(实例方法)

        thread.setName(线程名称), 设置线程名称。

         thread.getName()返回线程名称 。

        通过设置线程名称,有助于程序调试,提高程序的可读性, 建议为 每个线程都设置一个能够体现线程功能的名称

代码:

public class MyThread extends Thread {

    @Override
    public void run() {
        System.out.println("run 方 法 打 印 当 前 线 程 名 称 :" +
                Thread.currentThread().getName());
    }
}

测试代码:

public class Test {

    public static void main(String[] args) {

     MyThread  thread=new MyThread();
     thread.setName("帅气的线程");//设置线程名称,记得一定要在线程启动时设置
     thread.start();

    }
}

结果:

      

java Forkjoin 线程中打印traceId java 打印当前线程_多线程_02

 

 


1.3 isAlive() (实例方法)

        thread.isAlive()判断当前线程是否处于活动状态。

        活动状态就是线程已启动并且尚未终止。

代码:

public class MyThread extends Thread {

        @Override
        public void run() {
            
            //运行状态,true
            System.out.println("run 方法, isalive = " + this.isAlive()); 

}

测试代码:

public class Test {

    public static void main(String[] args) {

        MyThread t3 = new MyThread();

        System.out.println("begin==" + t3.isAlive()); //false,在启动线程之前
        t3.start();
        System.out.println("end==" + t3.isAlive());
        //结果不一定,打印这一行时,如果 t3线程还没结束就返回 true, 如果 t3 线程已结束,返回 false
    }
}

结果

       

java Forkjoin 线程中打印traceId java 打印当前线程_java_03

 

 


1.4 sleep() (类方法)

        Thread.sleep(millis):让当前线程休眠指定的毫秒数

        当前线程是指 Thread.currentThread()返回的线程

代码:

public class Mythread2 extends Thread {
    @Override
    public void run() {

        //给定60s时间
        int m=60;

        while(true){

            System.out.println(m);
            //相当于时间-1;
            m--;
            if (m<0){
                break;
            }

            //让线程没执行一次循环就休眠一秒
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

测试代码:

public class Test2 {
    public static void main(String[] args) {
        //创建线程
      Mythread2 mythread2=new Mythread2();
      mythread2.start();//启动线程
    }
}

结果:每秒减1

         

java Forkjoin 线程中打印traceId java 打印当前线程_System_04

 


实例方法)

        thread.getId()可以获得线程的唯一标识

        注意:

                某个编号的线程运行结束后,该编号可能被后续创建的线程使用

                重启的 JVM 后,同一个线程的编号可能不一样

代码:

public class MyThread extends Thread {

        @Override
        public void run() {
            System.out.println("thread name = " + Thread.currentThread().getName()
                    + ", id == " + this.getId() );
        }

}

测试代码:

public class Test2 {
    public static void main(String[] args) {
        //查看主线程id
        System.out.println( Thread.currentThread().getName() + " , id = "         
                            +Thread.currentThread().getId());

        //循环5次,创建5个子线程, 查看不同子线程的 id
        for(int i = 1; i <= 5; i++){
            new MyThread().start();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

结果:

        

java Forkjoin 线程中打印traceId java 打印当前线程_getId_05

 


1.6 yield() (类方法)

         Thread.yield()方法的作用是放弃当前的 CPU 资源

代码:

public class MyThread extends Thread {

        @Override
        public void run() {
            long begin = System.currentTimeMillis();
            long sum = 0;
            for(int i = 1; i <= 1000000; i++){
                sum += i;
                Thread.yield(); //线程让步, 放弃 CPU 执行权
            }
            long end = System.currentTimeMillis();
            System.out.println("子线程用时: " + (end - begin));
        }

}

测试代码:

public class Test {

    public static void main(String[] args) {

        //创建子线程并启动,开始计算累加
        MyThread myThread=new MyThread();
        myThread.start();

        //在 main 线程中计算累加和
        long begin = System.currentTimeMillis();
        long sum = 0;
        for(int i = 1; i <= 1000000; i++){
            sum += i;
        }
        long end = System.currentTimeMillis();
        System.out.println("main 方法 , 用时: "+(end-begin));
    }

结果:

        

java Forkjoin 线程中打印traceId java 打印当前线程_getId_06

结论:

        在代码中,main方法线程和子线程都进行了累加计算,但是,由于子线程的run()中使用了 Thread.yield()方法,导致子线程每执行一次累加,就要放弃其拥有的cpu资源,然后再进行排队,等待cpu分配资源,所以导致计算完累加耗时比较大 。

 


1.7 setPriority()(实例方法)

        thread.setPriority( num ); 设置线程的优先级。

        java 线程的优先级取值范围是 1 ~ 10 , 默认的优先级是5,如果超出这个范围会抛出异常 IllegalArgumentException。

         在操作系统中,优先级较高的线程获得 CPU 的资源越多。

        线程优先级本质上是只是给线程调度器一个提示信息,以便于调 度器决定先调度哪些线程. 注意不能保证优先级高的线程先运行。

        Java 优先级设置不当或者滥用可能会导致某些线程永远无法得到运行,即产生了线程饥饿。

        线程的优先级并不是设置的越高越好,一般情况下使用普通的优 先级即可,即在开发时不必设置线程的优先级。

        线程的优先级具有继承性, 在 A 线程中创建了 B 线程,则 B 线程的 优先级与 A 线程是一样的。

由于创建线程比较少,设置了看不出区别,所以这里不用代码演示了。


1.8 interrupt()(实例方法)

        中断线程.。

        注意调用 interrupt()方法仅仅是在当前线程打一个停止标志,并不是真正的停止线程

代码:

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i=0;i<10000;i++){
            if (this.isInterrupted()){
                System.out.println("当前线程的中断标志为 true, 我要退出了");
                break; //中断循环, run()方法体执行完毕,
            }
            System.out.println("子线程——》"+i);
        }
    }
}

测试代码:

public class Test {

    public static void main(String[] args) {

        MyThread t1 = new MyThread();
        t1.start(); //开启子线程

        //当前线程是 main 线程
        for(int i = 1; i<=1000; i++){
            System.out.println("main ==> " + i);
        }

        //中断子线程
        t1.interrupt(); //仅仅是给子线程标记中断,让子线程里面的isInterrupted()去识别


    }
}

结果:

        

java Forkjoin 线程中打印traceId java 打印当前线程_多线程_07

 结论:

        interrupt()方法仅仅是在当前线程打一个停止标志,并不是真正的停止线程,要想让线程真正的停止,必须要搭配线程的另一个捕获方法isInterrupted(),它用来判断当前线程是否被打了中断停止标志,有就放回布尔值true 没有就是false。


1.9 setDaemon()(实例方法)

         Java 中的线程分为用户线程与守护线程        

        守护线程是为其他线程提供服务的线程,如垃圾回收器(GC)就是一 个典型的守护线程

         守护线程不能单独运行, 当 JVM 中没有其他用户线程,只有守护线程时,守护线程会自动销毁, JVM 会退出。

代码:

public class MyThread extends Thread {
    @Override
    public void run() {
       //使用死循环,只有线程销毁时才会停止
        while(true){
            System.out.println("sub thread.....");
        }
    }
}

 测试代码:

public class Test {

    public static void main(String[] args) {

        MyThread t1 = new MyThread();
        //将当前线程设置为守护线程
        t1.setDaemon(true);
        t1.start(); //开启子线程

        //当前线程为 main 线程
        for(int i = 1; i <= 10000 ; i++){
            System.out.println("main== " + i);
        }

    //当 main 线程结束, 守护线程 thread 也销毁了

    }
}

结果:

         

java Forkjoin 线程中打印traceId java 打印当前线程_多线程_08

 结论:

        守护线程是可以人为设置的,而且它不能单独运行,当其他用户线程结束时,守护线程也会被销毁