线程学习-第二节

Thread构造函数

1.Thread构造函数有哪些

public Thread();
public Thread(Runnable target);
public Thread(ThreadGroup group, Runnable target);
public Thread(String name);
public Thread(ThreadGroup group, String name);
public Thread(Runnable target, String name);
public Thread(ThreadGroup group, Runnable target, String name);
public Thread(ThreadGroup group, Runnable target, String name,long stackSize);

以上是Thread相关的构造函数源码

2.线程的命名

2.1线程的默认命名

  线程的默认命名是:"Thread-"作为前缀与一个自增长数字进行字母组合,这个自增数字在整个JVM进程中将会不断自增;

默认命名的自增代码如下:

 public static void main(String[] args) {
        IntStream.range (0, 5).boxed ().map (
                i -> new Thread (() -> System.out.println (Thread.currentThread ().getName ()))).forEach (Thread::start);
    }

控制台打印输出如下:

Thread-0
Thread-2
Thread-1
Thread-3
Thread-4
Thread-5

2.2修改线程的命名

修改线程的实例代码如下:

   private final static String PREFIX = "HELLO-";
    public static void main(String[] args) {
        IntStream.range (0,5).mapToObj (ThreadNameTest1::createThread).forEach (Thread::start);
    }
    private static Thread createThread(final int intName) {
       return new Thread (() -> System.out.println (Thread.currentThread ().getName ()), PREFIX + intName);
    }

控制台打印输出:

HELLO-0
HELLO-1
HELLO-2
HELLO-3
HELLO-4

从上面的线程可以看出,线程是可以修改名称的,并且给线程的命名有助于在实际开发中追踪线程的并发问题

3.线程的父子关系

在Thread的构造方法中都会去调用一个init构造方法,新创建的任何一个线程都会有一个父线程
     1. 一个线程的创建是另一个线程完成的;
     2. 被创建线程的父线程是创建它的线程;

Thread中init的源码如下:

private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name.toCharArray();

        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 (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 */
        tid = nextThreadID();
    }

4.线程和线程组

	线程与线程组的关系代码测试如下:
		Thread t1 = new Thread ("t1");

        ThreadGroup group = new ThreadGroup ("TestGroup");

        Thread t2 = new Thread (group, "t2");

        ThreadGroup mainGroupThread = Thread.currentThread ().getThreadGroup ();

        System.out.println ("主线程是哪个线程组:" + mainGroupThread.getName ());

        System.out.println ("t1线程和主线程是相同的组:" + (mainGroupThread == t1.getThreadGroup ()));

        System.out.println ("t2线程不属于主线程组:" + (mainGroupThread == t2.getThreadGroup ()));

        System.out.println ("t2线程组是属于主线程TestGroup的组:" + (t2.getThreadGroup ()== group));

控制台输出:

主线程属于哪个组:main
t1线程和主线程是相同的组:true
t2线程组不属于主线程组:false
t2线程组是属于主线程TestGroup的组:true
分析线程和线程组的关系得出:
  1. main线程所在的ThreadGroup称为:main;
  2. 构造一个线程的时候没有显示的执行ThreadGroup,它就和父线程同属于一个ThreadGoup

5.Thread与Runnable

Thread负责的是线程本身相关的职责和控制,而Runnable则负责逻辑执行单元的部分

6.守护线程

6.1守护线程的概念

 守护线程是后台线程,也就是执行的自定义线程,如果JVM中没有一个非守护线程,JVM的进程就会推出

6.2守护线程的作用

守护线程经常用作与执行后台任务,因此有时它也称为后台线程,当你希望关闭某些线程的时候,或者推出JVM进程的时候,一些线程能够自动关闭,此时可以考虑守护线程来完成这样的工作

6.2守护线程的代码测试

   public static void main(String[] args) {
        Thread thread = new Thread (() -> {
            while (true) {
                try {
                    Thread.sleep (100);
                } catch (InterruptedException e) {
                    e.printStackTrace ();
                }
            }
        });
        thread.setDaemon (true);// 设置为守护线程
        thread.start ();
        System.out.println ("finally");
    }

设置守护线程,调用setDaemon (true)方法即可,设置守护线程只能在线程启动之前进行设置,如果一个线程已经死亡了,那么再设置setDaemon ()就会抛出异常 IllegalThreadStateException

Exception in thread "main" java.lang.IllegalThreadStateException
	at java.lang.Thread.setDaemon(Thread.java:1352)
	at com.hyq.thread.threadtest.ThreadDaemon.main(ThreadDaemon.java:22)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值