【并发编程】Thread类的详细介绍

简介: 【并发编程】Thread类的详细介绍

Thread类是Java中实现多线程编程的基础类。本篇博客就来介绍下Thread类的常用API和常见用法。

Thread类常用的方法如下:

  • Thread.activeCount():这个方法用于返回当前线程的线程组中活动线程的数量,返回的值只是一个估计值,因为当此方法遍历内部数据结构时,线程数可能会动态更改。)。
  • Thread.checkAccess(): 检验当前正在执行的线程是否有权限修改thread的属性,这个方法我们一般不自己进行调用,Thread类的set方法在进行属性修改时都会先调用这个方法。
  • Thread.currentThread():获取当前正在运行的线程。
  • Thread.dumpStack():输出线程栈,一般在debug的时候调用。
  • Thread.enumerate(Thread tarray[]):??使用场景。
  • Thread.getAllStackTraces():获取系统中所有线程的线程栈信息。
  • thread.getName():获取线程的名字。
  • thread.getPriority():获取线程的优先级。
  • thread.getStackTrace():获取堆栈信息。
  • thread.getState():获取线程状态。
  • thread.getThreadGroup():获取线程所在线程组。
  • thread.interrupt():使得指定线程中断阻塞状态,并将阻塞标志位置为true。
  • thread.interrupted():测试当前线程是否被中断。
  • thread.isAlive():判断线程是否还存活着。
  • thread.isDaemon():判断线程是否是守护线程。
  • thread.join():在当前线程中加入指定线程,使得当前线程必须等待指定线程运行结束之后,才能结束。可以理解成线程插队、等待该线程终止。
  • Thread.sleep(long):强制线程睡眠一段时间。
  • thread.start():启动一个线程。
  • thread.setName(name):设置线程的名字。
  • thread.setPriority(priority):设置线程的优先级。
  • thread.setDaemon(true):将指定线程设置为守护线程。
  • thread.yield():使得当前线程退让出CPU资源,把CPU调度机会分配给同样线程优先级的线程。
  • object.wait()、object.notify()、object.notifyAll():Object类提供的线程等待和线程唤醒方法。

示例代码

 
public class MyThread  {
 
    public static void main(String[] args) {
          Thread thread = Thread.currentThread();
        
                //这个方法返回的是当前线程所在线程组以及这个线程组的子线程组内活动的线程数
                //这个值是一个估计值,所以这个方法的应用场景不大
                int activeCount = Thread.activeCount();
                System.out.println("当前系统中活动线程数["+activeCount+"]");
        
                //向标准错误输出流输出当前的线程栈,不会阻断程序的继续执行
                Thread.dumpStack();
        
                //获取所有线程栈信息
                Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
        
                //获取类加载器
                ClassLoader contextClassLoader = thread.getContextClassLoader();
        
                //获取当前线程名字
                String threadName = thread.getName();
                System.out.println("current thread name["+threadName+"]");
        
                //获取当前线程ID
                long threadId = thread.getId();
                System.out.println("current thread id["+threadId+"]");
        
                //获取当前线程的优先级,一共有1~10总共10个优先级,这个优先级并不是在
                //所有平台都生效的
                int priority = thread.getPriority();
                System.out.println("current thread priority["+priority+"]");
        
                StackTraceElement[] stackTrace = thread.getStackTrace();
                System.out.println("-------------stackTrace info--------------");
                for (int i = 0; i < stackTrace.length; i++) {
                    StackTraceElement element = stackTrace[i];
                    System.out.println("className:["+element.getClassName()+"]");
                    System.out.println("fileName:["+element.getFileName()+"]");
                    System.out.println("line nunber:["+element.getLineNumber()+"]");
                    System.out.println("method name:["+element.getMethodName()+"]");
                    System.out.println("is native method:["+element.isNativeMethod()+"]");
                    System.out.println("------------------------------------------");
                }
        
                Thread.State state = thread.getState();
                System.out.println("thread state:["+state+"]");
        
                ThreadGroup threadGroup = thread.getThreadGroup();
                String threadGroupName = threadGroup.getName();
                System.out.println("thread group name:["+threadGroupName+"]");
        
                //线程睡眠,调用sleep方法会使得线程进入timed_waiting状态,如果线程已经
                //获得了锁资源,调用sleep方法是不会释放这个锁的
                Thread.sleep(2000,500);
                Thread.sleep(1000);
                TimeUnit.SECONDS.sleep(2);
        
                Thread thread1 = new Thread(new Runnable() {
                    @SneakyThrows
                    @Override
                    public void run() {
                        TimeUnit.SECONDS.sleep(100);
                    }
                });
                thread1.start();
                thread1.join(50);
 
    }
 
 
}

守护线程

守护线程可以理解为服务线程,他们的作用就是服务于其他用户线程。当系统中不存在其他用户线程时,这些守护线程也会自动消亡。比如JVM的垃圾清理线程就是守护线程。我们可以使用如下方法查看和设置线程是否是守护线程。

thread.isDaemon();
thread.setDaemon(true);

join方法

调用线程的join方法会使得调用线程进入waiting状态,直到被调用的线程执行结束,调用线程才会重新获得执行的机会。

 
public class MyThread  {
 
    public static void main(String[] args) throws Exception {
    
        Thread thread1 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                TimeUnit.SECONDS.sleep(100);
            }
        });
        thread1.start();
        thread1.join();
        System.out.println("main thread end...");
    }
 
}

上面的代码中,main线程调用了thread1的join方法,main线程会被挂起进入waiting状态,直到thread1执行完毕之后,main线程才有机会重新获得执行机会。

join方法还有一个重载方法,这个方法可以指定超时时间。

thread1.join(50);

如果thread1线程在50ms内还没执行完,main线程就可以重新获得执行机会。

yeild方法

调用线程的yield方法不是一定会成功。

  • 退让成功时,退让线程会由Running(运行)转为Runnable(就绪)状态。
  • 退让了的线程,与其他同优先级级别的线程一样,同样有再次获取CPU使用权的机会。

中断

先贴上一段网友对线程中断的总结。

  • 除非是线程自己interrupt()自己,否则checkAccess()方法都会被调用,并可能抛出一个SecurityException异常。
    如果当前线程处于blocked阻塞(因为调用wait、sleep和join造成的)状态时被interrupt了,那么[中断标志位]将被清除,并且收到一个InterruptedException异常。
  • 如果当前线程处于blocked阻塞(因为NIO的InterruptibleChannel进行的I/O操作造成的)状态时被interrupt了,则会关闭channel,[中断标志位]将会被置为true,并且当前线程会收到一个ClosedByInterruptException异常。
  • 如果当前线程处于blocked阻塞(因为NIO的Selector造成的)状态时被interrupt了,那么[中断标志位]将被置为true,然后当前线程会立即从选择器区域返回并返回值(可能为非零的值)。
  • 如果前面的情况都没有发生,则线程会将[中断标志位]将被置为true。

更加易懂的说法(不包括NIO部分):

  • interrupt()方法并不是中断线程,而是中断阻塞状态,或者将线程的[中断标志位]置为true。
  • 对于未阻塞的线程,interrupt()只是造成[中断标志位]=rue,线程本身运行状态不受影响。
  • 对于阻塞的线程,interrupt()会中断阻塞状态,使其转换成非阻塞状态,并清除[中断标志位]。
  • 造成阻塞状态的情况有:sleep()、wait()和join()。
  • 阻塞状态的线程被中断时,只是中断了阻塞状态,即sleep()、wait()和join(),线程本身还在继续运行。
相关文章
|
数据可视化 前端开发 Java
SpringBoot 集成 Flowable + Flowable Modeler 流程配置可视化(图解)(一)
SpringBoot 集成 Flowable + Flowable Modeler 流程配置可视化(图解)
3977 0
|
SQL 关系型数据库 MySQL
JPQL-Query查询实例详解
JPQL-Query查询实例详解
444 0
|
存储 JSON Kubernetes
Kubernetes必备知识: Annotations
Annotations(注解) 是 key/value 形式附加于对象的注解。不同于 Labels 用于标志和选择对象,Annotations 则是用来记录一些附加信息,用来辅助应用部署、安全策略以及调度策略等。比如 deployment 使用 annotations 来记录 rolling update 的状态。
5757 0
|
消息中间件 JSON Java
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
27476 0
|
开发工具 git 开发者
gitlab没有push权限,重设账号密码仍然不行,问题解决
这篇文章讲述了解决GitLab中因权限问题导致的无法推送代码到受保护分支的问题,通过提升用户权限至维护者解决了问题。
473 0
gitlab没有push权限,重设账号密码仍然不行,问题解决
|
存储 NoSQL Java
Java 使用 Redis
10月更文挑战第22天
266 0
|
消息中间件 存储 Cloud Native
RocketMQ从4.9.7 升级到5.3.0有什么变化?
【8月更文挑战第25天】RocketMQ从4.9.7 升级到5.3.0有什么变化?
875 4
|
SQL NoSQL JavaScript
04 MongoDB各种查询操作 以及聚合操作总结
文章全面总结了MongoDB中的查询操作及聚合操作,包括基本查询、条件筛选、排序以及聚合管道的使用方法和实例。
2578 0
|
消息中间件 NoSQL Linux
详解Redis的主从同步原理
只不过在主节点中叫做master_repl_offset; 从节点也有一个偏移量叫做slave_repl_offset,用来记录从节点已经从主节点的repl_backlog_buffer中同步到的最新写指令的位置;
2208 3
|
Java 测试技术 持续交付
如何使用Spring Boot进行单元测试
如何使用Spring Boot进行单元测试

热门文章

最新文章