美文网首页
Java多线程学习-1

Java多线程学习-1

作者: 邵增卫 | 来源:发表于2019-05-02 22:21 被阅读0次
    1. 创建Java线程
      Java中Thread类采用了模板设计模式,像下面的方式创建一个线程,不会做任何操作,在启动之后会迅速退出。
       // 创建一个Thread对象,但并没有创建一个线程
        Thread thread = new Thread();
       // 启动线程
        thread.start(); 
    

    Thread类中的run方法做为执行单元,一般在创建具体的业务线程的时候都必须要重写run方法,以实现真正的业务逻辑。

    引入策略模式(Runnable接口)使得业务逻辑与线程的控制逻辑分离后,业务逻辑更加清晰。所以大多数情况都会采用实现Runnable的方式实现Java的多线程。

    public class MyRunnable implements Runnable {
        public void run() {
           System.out.println("here is the system logic");
       }
    }
    
    Thread thread = new Thread(new MyRunnable());
    thread.start();
    
    1. Thread 的构造函数


      Thread API.jpg

      从上面可以看到Thread的构造函数,主要有Runnable(业务逻辑),ThreadGroup(线程组),name(线程名)以及stackSize(线程栈)四个参数。最主要的参数业务逻辑并不需要多做任何介绍,线程组和线程名两个参数有必要进行一下介绍。

    2.1 线程名
    为一个业务线程取一个合适的名字,当业务在出现问题的时候可以快速定位到问题,那么如果线程没有取名的话,默认线程会以”Thead-“做为前缀和一个自增的自然数做为线程名(注意是线程调用start方法的顺序递增,而不是创建Thread对象的顺序)。

    线程名的修改,在线程启动之前是可以通过setName方法修改的,不过在线程启动之后,线程名将不能再修改。

    2.2 ThreadGroup
    在介绍ThreadGoup之前,首先要介绍一下Thread的父子关系,通过分析Thread类的init方法的源码我们可以发现,Thread的parent为创建线程的线程做为父线程;如果在创建线程之前没有指定ThreadGroup时,会将父线程的ThreadGroup做为当前线程的ThreadGroup;子线程将父线程的priority和daemon做为自己的priority和daemon。

    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;
    
          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();
      }
    
    1. Deamon 线程
      在搞清楚Deamon之前,首先要搞清楚一个问题:JVM虚拟机会在什么时候退出?
      在JVM虚拟机官方文档中: The JVM will exits when the only threads running are all daemon threads. (当虚拟机的所有线程只有守护线程时,虚拟机将会退出。)

    3.1 怎样创建一个daemon thread
    在线程调用start之前,通过setDaemon(true)方法可以将线程设置为守护线程。注意在线程启动之后,调用setDaemon会抛出异常。通过isDaemon方法可以判断这个线程是否是守护线程。

    以上仅仅是线程的最基本的属性,在业务中使用多线程,我们还需要进一步学习线程的更多特性和API。

    相关文章

      网友评论

          本文标题:Java多线程学习-1

          本文链接:https://www.haomeiwen.com/subject/dlkonqtx.html