Java并发04:Thread的基本方法(1)-Name、ThreadGroup、activeCount、isAlive、守护线程等

本章主要对Java中Thread类的基本方法进行学习。

1.序言

Thread类作为线程的基类,提供了一系列方法,主要有:

  • Thread.sleep(long):强制线程睡眠一段时间。
  • Thread.activeCount():获取当前程序中存活的线程数。
  • thread.start():启动一个线程。
  • Thread.currentThread():获取当前正在运行的线程。
  • thread.getThreadGroup():获取线程所在线程组。
  • thread.getName():获取线程的名字。
  • thread.getPriority():获取线程的优先级。
  • thread.setName(name):设置线程的名字。
  • thread.setPriority(priority):设置线程的优先级。
  • thread.isAlive():判断线程是否还存活着。
  • thread.isDaemon():判断线程是否是守护线程。
  • thread.setDaemon(true):将指定线程设置为守护线程。
  • thread.join():在当前线程中加入指定线程,使得当前线程必须等待指定线程运行结束之后,才能结束。可以理解成线程插队等待该线程终止
  • thread.yield():使得当前线程退让出CPU资源,把CPU调度机会分配给同样线程优先级的线程。
  • thread.interrupt():使得指定线程中断阻塞状态,并将阻塞标志位置为true。
  • object.wai()、object.notify()、object.notifyAll():Object类提供的线程等待和线程唤醒方法。

为了便于阅读,将以上所有方法,放在5篇文章中进行学习。

本章主要学习绿色字体标记的方法。

1.Thread方法学习

1.1.线程休眠

Thread.sleep(long):强制线程睡眠一段时间,其中long的单位为毫秒

线程休眠:休眠的时间可以用于让其他线程完成当前工作,亦可以减少CPU占用时间,但是不会释放锁持有的锁。可以理解成坐在座位上发呆

示例代码:

//通过Thread.sleep(ms),指定当前线程进行休眠(但是并没有释放锁)
LOGGER.info("通过Thread.sleep(ms),指定当前线程进行休眠(但是并没有释放锁)");
LOGGER.info("现在时间:" + System.currentTimeMillis() + ",main线程即将休眠1000ms.");
Thread.sleep(1000);
LOGGER.info("休眠结束:" + System.currentTimeMillis() + "\n");

运行结果:

2018-03-12 11:46:06 INFO  ThreadBasicDemo:20 - 通过Thread.sleep(ms),指定当前线程进行休眠(但是并没有释放锁)
2018-03-12 11:46:06 INFO  ThreadBasicDemo:21 - 现在时间:1520826366873,main线程即将休眠1000ms.
2018-03-12 11:46:07 INFO  ThreadBasicDemo:23 - 休眠结束:1520826367873

1.2.线程启动与存活线程数

Thread.activeCount():获取当前程序中存活的线程数。
thread.start():启动一个线程。

示例代码:

//通过Thread.activeCount(),获取程序活着的线程数。
LOGGER.info("通过Thread.activeCount(),获取程序活着的线程数");
LOGGER.info("当前程序活着的线程数:" + Thread.activeCount() + ",一个是main线程,一个是GC线程。");
//添加一个线程
new Thread(() -> {
    try {
        Thread.sleep(10);//存活10毫秒,方便后续代码能够统计到此线程
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();
LOGGER.info("添加一个匿名线程之后,活着的线程数:" + Thread.activeCount());
Thread.sleep(15);//等着内部匿名线程死掉
LOGGER.info("匿名线程死掉之后,活着的线程数:" + Thread.activeCount() + "\n");

运行结果:

2018-03-12 11:46:07 INFO  ThreadBasicDemo:26 - 通过Thread.activeCount(),获取程序活着的线程数
2018-03-12 11:46:07 INFO  ThreadBasicDemo:27 - 当前程序活着的线程数:2,一个是main线程,一个是GC线程。
2018-03-12 11:46:07 INFO  ThreadBasicDemo:36 - 添加一个匿名线程之后,活着的线程数:3
2018-03-12 11:46:07 INFO  ThreadBasicDemo:38 - 匿名线程死掉之后,活着的线程数:2

关于Thread.sleep(long)在后续章节中还会继续学习。

1.3.当前线程、线程组、线程名、优先级、线程存活

Thread.currentThread():获取当前正在运行的线程。
thread.getThreadGroup():获取线程所在线程组。
thread.getName():获取线程的名字。
thread.getPriority():获取线程的优先级。
thread.setName(name):设置线程的名字。
thread.setPriority(priority):设置线程的优先级。
thread.isAlive():判断线程是否还存活着。

示例代码:

new Thread(() -> {
    //通过Thread.currentThread()获取当前线程
    LOGGER.info("通过Thread.currentThread()获取当前线程");
    Thread currentThread = Thread.currentThread();
    LOGGER.info("当前线程:" + currentThread);
    LOGGER.info("当前线程-名字(thread.getName()):" + currentThread.getName());
    LOGGER.info("当前线程-优先级(thread.getPriority()):" + currentThread.getPriority());
    LOGGER.info("当前线程-线程组名字:" + currentThread.getThreadGroup().getName() + "\n");

    //通过thread.setName(name)设置线程名
    LOGGER.info("通过thread.setName(name)设置线程名");
    currentThread.setName("张三");
    //通过thread.setPriority(priority)设置优先级
    LOGGER.info("通过thread.setPriority(priority)设置优先级");
    currentThread.setPriority(Thread.MAX_PRIORITY);
    LOGGER.info("修改名字和优先级之后:" + currentThread);

    //通过thread.isAlive()判断当前线程是否还活着
    LOGGER.info("通过thread.isAlive()判断当前线程是否还活着:" + currentThread.isAlive() + "\n");
}).start();

运行结果:

2018-03-12 11:46:07 INFO  ThreadBasicDemo:42 - 通过Thread.currentThread()获取当前线程
2018-03-12 11:46:07 INFO  ThreadBasicDemo:44 - 当前线程:Thread[Thread-1,5,main]
2018-03-12 11:46:07 INFO  ThreadBasicDemo:45 - 当前线程-名字(thread.getName()):Thread-1
2018-03-12 11:46:07 INFO  ThreadBasicDemo:46 - 当前线程-优先级(thread.getPriority()):5
2018-03-12 11:46:07 INFO  ThreadBasicDemo:47 - 当前线程-线程组名字:main

2018-03-12 11:46:07 INFO  ThreadBasicDemo:50 - 通过thread.setName(name)设置线程名
2018-03-12 11:46:07 INFO  ThreadBasicDemo:53 - 通过thread.setPriority(priority)设置优先级
2018-03-12 11:46:07 INFO  ThreadBasicDemo:55 - 修改名字和优先级之后:Thread[张三,10,main]
2018-03-12 11:46:07 INFO  ThreadBasicDemo:58 - 通过thread.isAlive()判断当前线程是否还活着:true

说明:

  • 关于线程的字符串描述Thread[Thread-1,5,main],三个值分别代表:线程名、优先级和线程组名。

关于线程优先级在后续章节中还会继续学习。

1.4.守护线程的判断与设置

thread.isDaemon():判断线程是否是守护线程。
thread.setDaemon(true):将指定线程设置为守护线程。

守护线程:也可以称之为后台线程非用户线程,即随系统结束而结束的线程。

更容易理解的说法:当前程序中,只剩下main线程和守护线程,且main线程执行完毕时,则系统结束。

与用户线程的区别:例如一个线程中通过while(true)无限等待。如果是用户线程,那么这个程序永远都不会关闭;如果是守护线程,那么当其他的用户线程执行完毕之后,程序及会关闭。

示例代码:

LOGGER.info("所谓[守护线程],可以理解为后台线程或非用户线程。");
LOGGER.info("当前程序中,只剩下main线程和守护线程,且main线程执行完毕时,系统结束。");
//守护线程
Thread normalThread = new Thread(() -> {
    try {
        while (true) {
            Thread.sleep(1000);
            LOGGER.info("normalThread线程正在工作...");
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});
Thread daemonThread = new Thread(() -> {
    try {
        while (true) {
            Thread.sleep(1000);
            LOGGER.info("daemonThread线程正在工作...");
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});
LOGGER.info("通过thread.isDaemon()判断当前线程[normalThread]是否是守护线程:" + normalThread.isDaemon());
LOGGER.info("通过thread.isDaemon()判断当前线程[daemonThread]是否是守护线程:" + daemonThread.isDaemon());
LOGGER.info("通过thread.setDaemon(true)将指定线程设置为守护线程,随main线程结束而结束。");
daemonThread.setDaemon(true);
LOGGER.info("通过thread.isDaemon()判断当前线程[daemonThread]是否是守护线程:" + daemonThread.isDaemon());
if (false) {
    normalThread.start();
} else {
    daemonThread.start();
}

Thread.sleep(2000);//等待线程死掉
LOGGER.info("normalThread是否存活:" + normalThread.isAlive());
LOGGER.info("daemonThread是否存活:" + daemonThread.isAlive());

运行结果:

2018-03-12 11:46:08 INFO  ThreadBasicDemo:62 - 所谓[守护线程],可以理解为后台线程或非用户线程。
2018-03-12 11:46:08 INFO  ThreadBasicDemo:63 - 当前程序中,只剩下main线程和守护线程,且main线程执行完毕时,系统结束。
2018-03-12 11:46:08 INFO  ThreadBasicDemo:85 - 通过thread.isDaemon()判断当前线程[normalThread]是否是守护线程:false
2018-03-12 11:46:08 INFO  ThreadBasicDemo:86 - 通过thread.isDaemon()判断当前线程[daemonThread]是否是守护线程:false
2018-03-12 11:46:08 INFO  ThreadBasicDemo:87 - 通过thread.setDaemon(true)将指定线程设置为守护线程,随main线程结束而结束。
2018-03-12 11:46:08 INFO  ThreadBasicDemo:89 - 通过thread.isDaemon()判断当前线程[daemonThread]是否是守护线程:true
2018-03-12 11:46:09 INFO  ThreadBasicDemo:79 - daemonThread线程正在工作...
2018-03-12 11:46:10 INFO  ThreadBasicDemo:79 - daemonThread线程正在工作...
2018-03-12 11:46:10 INFO  ThreadBasicDemo:97 - normalThread是否存活:false
2018-03-12 11:46:10 INFO  ThreadBasicDemo:98 - daemonThread是否存活:true

 

posted @ 2020-10-26 18:14  姚春辉  阅读(361)  评论(0编辑  收藏  举报