我是靠谱客的博主 专注诺言,最近开发中收集的这篇文章主要介绍Java基础之线程介绍篇,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

提到Java线程的话,无非就是Runnable、Thread、ThreadGroup了。ThreadGroup是记录了一些线程组中的信息,线程组的名称了、线程组的活跃线程数量了等等,我们今天重点说一下Thread这个类中的方法。

Runnable是提供了线程运行的基础方法(也就是run方法)接口,而Thread才是操作真正线程的类,然而Thread中也有run方法,大家可以看下,这个run方法也是实现了Runnable接口中的,所以,如果你只是想实现一个线程运行的目标(target)就仅实现Runnable接口,如果你想启动线程、终止线程等就extends吧。接下来我们去看下Thread类中的方法。

不知道大家有看java帮助文档的习惯没,我个人挺喜欢看帮助文档的,大致了解一下类、接口的功能。

以下帮助文档使用的是1.6的,源码使用的1.8的源码。

1、我们可以看到Thread类继承自Object类,说明Thread中有Object中的方法

2、Java允许多线程的执行

3、每个线程都有优先级之分(优先级取决去创建该线程的当前线程的优先级),每个线程都可以标记为守护线程和非守护线程(创建该线程的当前线程是守护线程和非守护线程)

4、Java创建线程有两种方法

我们去看下Thread源码中的执行方法(还是先看帮助文档,在去研究源码中的具体方法):

 1、Thread类中的嵌套类(Thread.State-线程状态。Thread.UncaughtExceptionHandler-异常未捕获时执行的接口)。我们可以看到有State记录线程状态,有程序可以处理线程出现异常情况

2、我们可以看到有线程的最大优先级、最小优先级以及默认优先级

3、就是一些构造方法了,有各种各样的构造方法。(这些构造方法可以自行去查看内容)

接下来是我们的重点了,我们的Thread中有那些方法,我们可以拿来干什么?

方法太多了,只截取了一部分。我们把主要的方法领出来说明一下:

 1、activeCount-返回当前线程的线程组中的活动线程数目

    public static int activeCount() {
        //我们可以看到源码是获取了当前线程所在线程组,从而获取到活动线程数目
        return currentThread().getThreadGroup().activeCount();
    }

2、getId、getName、getPriority。获取线程id、线程名称、线程优先级等三个方法,我们平时基本用的时候没有初始化过这三个参数吧,我们看下源码是怎么帮我们分配的这些参数吧。

我们可以看到我们新构造Thread时,系统帮我们生成了线程id(内部维护了一个int值)、线程名称(Thread-数字)、把当前正在运行的线程守护还是非守护设置给新线程(当前线程是守护线程则新线程也为守护线程)、当前正在运行的线程的优先级设置给新线程(当前正在运行的线程优先级是多少,新线程的优先级是多少)、把当前正在运行的线程的线程组设置给新线程(当前线程和新线程同在一个线程组中)

    //我们平常最常写的创建线程的方式
    public Thread(Runnable target) {
        //内部执行了init方法
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
    
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
    }

    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
        //初始化线程的名字
        this.name = name;
      
        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                //获取当前线程的线程组
                g = parent.getThreadGroup();
            }
        }

        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();

        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();
        //把当前线程的线程组分配给新构造的线程(也就是说新构造的线程和当前正在执行的线程同在一个线程组中)
        this.group = g;
        //当前线程是守护线程还是非守护线程并赋给新线程
        this.daemon = parent.isDaemon();
        //当前线程的优先级赋给新线程
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        //设置了线程id
        tid = nextThreadID();
    }

3、interrupt(中断线程)、interrupted(测试线程是否中断)。这两个方法没什么好说的就是中断线程的,这里说出来只是因为又一次面试官问我:如果停止一个线程?我就知道一个抛出异常,尴尬了

4、setUncaughtExceptionHandler(设置该线程由于未捕获到异常而突然终止时调用的处理程序。线程抛出异常时,你希望执行的程序)。比如你有一个转账的线程,因为数据库操作异常了,你希望将这条异常数据记录下来,则将你的保存记录的代码写到这个程序中

5、join、join(long millis)、join(long millis, int nanos)、sleep、sleep(long millis)、sleep(long millis, int nanos)以及yield()方法。网上有很多解释,我这里在简单说一下。

thread.join方法是等待该线程结束,也就是当前线程不往下执行,等thread这个线程执行完才继续执行,可以用来控制线程执行顺序。

Thread.sleep()使当前线程睡眠、睡眠一段时间。不释放对象锁,仅仅是等待

Thread.yield()暂停当前正在执行的线程对象,并执行其他线程。关键之一就是此方法使得对象锁释放,也就是说拥有对象锁权利的线程都可能执行(包括此线程,因为他也有执行对象的权利)。

 

 

最后

以上就是专注诺言为你收集整理的Java基础之线程介绍篇的全部内容,希望文章能够帮你解决Java基础之线程介绍篇所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(67)

评论列表共有 0 条评论

立即
投稿
返回
顶部