Java多线程~Thread类及其常见方法

Java多线程~Thread类及其常见方法,第1张

目录

Thread类及常见方法

Thread类的常见构造方法

Thread的几个常见属性

线程的启动-start()

start()使用示例

start()与run()的区别?

等待一个线程-join()

获取当前线程

休眠当前线程

线程的中断 


Thread类及常见方法

Thread类是JVM用来管理线程的一个类,即每个线程都有一个唯一的Thread对象与之关联

Thread类的常见构造方法

· 线程构造方法的使用

用来创建线程,具体的使用介绍在上篇博客有提到:创建线程的方式

        Thread t1 = new Thread();
        Thread t2 = new Thread(new MyRunnable());
        Thread t3 = new Thread("线程1");
        Thread t4 = new Thread(new MyRunnable(), "线程2");
Thread的几个常见属性

首先创建一个线程并启动,用来演示下列属性的获取方法

public class getAttribute {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){}
            }
        });
        t.start();
    }
}

· ID:ID是线程的唯一标识,不同线程不会重复

获取方法:getID()

System.out.println(t.getId());

· 名称:名称是在各种调试工具中用到的

获取方法:getName()

System.out.println(t.getName());

· 状态:状态表示线程当前所处的一个情况,本篇博客后面会详细讲述.

获取方法:getState()

System.out.println(t.getState());

· 优先级:优先级高的线程理论上来说更容易被调度到

获取方法:getPriority()

System.out.println(t.getPriority());

· 是否为后台线程:JVM会在一个进程的所有非后台线程结束后,才会结束运行

获取方法:isDaemon()

System.out.println(t.isDaemon());

· 是否存活:简单理解为run方法是否结束运行 

获取方法:isAlive()

System.out.println(t.isAlive());

线程的启动-start()

thread.start():申请系统调度,执行thread中的任务(重写的run方法).

start()使用示例

例如,利用Thread类实例化一个线程t,利用t调用start方法.

public class StartRun {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t线程启动");
            }
        },"t线程");
        t.start();
    }
}

补充:main方法的执行,也是存在一个main线程,在上述程序中main线程执行利用Thread创建t线程的代码,但main线程不会执行run方法,run方法是t线程执行的. 

start()与run()的区别?

①start是启动线程的方式

②run是属于线程任务的描述

以如下代码来介绍start和run到底哪个是启动线程的方式

· 线程对象.run,属于普通对象的实例方法调用,并没有启动线程,此时一直是main线程在运行

    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t线程 run");
            }
        },"t线程");
        t.run();
    }

 

 · 多个线程,同时存在并发和并行现象,下述代码同时存在main线程和t线程,main线程:①new Runnable对象、②new Thread对象、③t.start()、④执行输出语句;t线程:t线程在启动线程后调用run方法.

public class StartRun {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t线程 run");
            }
        },"t线程");
        t.start();
        System.out.println("t线程 start,main");
    }
}

 

等待一个线程-join()

在多线程的应用中,经常会需要等待一个线程完成它的工作后,才能进行自己的下一步工作.例如转账,假如A给B转账,只有等到A成功转账给B后,B才能决定是否存钱,这时就需要一个方法来明确等待线程的结束.

· join():t线程一直运行态,main线程一直等待态

例如:

public class ThreadJoin {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t线程 run");
                while(true){}
            }
        },"t线程");
        t.start();
        t.join();
        System.out.println("t线程start 这是main线程");
    }
}

  

· join(millis):等待线程运行结束,最多等待millis毫秒,例如下列代码,t线程先打印,然后一直运行,main线程等3秒打印,然后结束.

public class ThreadJoin {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t线程 run");
                while(true){}
            }
        },"t线程");
        t.start();
        t.join(3000);
        System.out.println("t线程start 这是main线程");
    }
}

假如目前有t线程和main线程,拿上述两个示例为例:

①t线程一直处于运行态,而main线程处于等待状态

②t线程先打印,然后一直运行,main线程等待3秒后执行打印,然后结束,此时t线程一直也处于运行态.

获取当前线程

当前线程一般指的是某行代码所在的线程,它返回的是当前线程的引用对象.

//返回当前线程对象的引用
public static Thread currentThread();
public class CurrentThread {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        },"子线程").start();
        System.out.println(Thread.currentThread().getName());
    }
}

 

休眠当前线程

直接利用Thread类名.sleep即可,让当前线程休眠(超时等待)指定时间,具体用法如下:

public class Sleep {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            }
        },"子线程");
        t.start();
    }
}

程序运行起来3秒后打印出当前线程的名称. 

 

线程的中断 

· 使用自定义的变量来作为标志位

需要给标志位上加volatile关键字,自定义标志位如果当线程处于等待/超时等待/阻塞,就没办法中断了

public class ThreadDemo {
    private static volatile boolean isInterrupt = false;

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i<10 && !isInterrupt; i++) {
                    System.out.println(i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.start();
        Thread.sleep(3000);
        isInterrupt = true;
    }
}

· 使用Thread.interrupted()或者Thread.currentThread().isInterrupted()代替自定义标志位 

Thread内部包含了一个boolean类型的变量作为线程是否被中断的标记

 例如下列代码

public class ThreadDemo1 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while(!Thread.currentThread().isInterrupted()) {
                        for (int i = 0; i < 10; i++) {
                            System.out.println(i);
                            Thread.sleep(1000);
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("出现异常时中断标志位:>" + Thread.currentThread().isInterrupted());
                }
            }
        });
        t.start();
        Thread.sleep(3000);
        t.interrupt();
    }
}

 在调用api中断时,即使线程处于等待状态,也会被直接中断.

 

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/800156.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存