Java Thread 的创建

public Thread() {
    this(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(ThreadGroup group, Runnable target, String name,
              long stackSize) {
    this(group, target, name, stackSize, null, true);
}
private Thread(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();
   
    if (g == null) {
     
        if (security != null) {
            g = security.getThreadGroup();
        }

        if (g == null) {
        */
            g = parent.getThreadGroup();
        // }
    }

    
    g.checkAccess();

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

    g.addUnstarted();

    this.group = g;
    this.daemon = parent.isDaemon();
    this.priority = parent.getPriority();
    // Android-changed: Moved into init2(Thread, boolean) helper method.
    /*
    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;
    
    init2(parent, inheritThreadLocals);

    /* Stash the specified stack size in case the VM cares */
    this.stackSize = stackSize;

    /* Set thread ID */
    this.tid = nextThreadID();
}
private void init2(Thread parent, boolean inheritThreadLocals) {
    this.contextClassLoader = parent.getContextClassLoader();
    this.inheritedAccessControlContext = AccessController.getContext();
    if (inheritThreadLocals && parent.inheritableThreadLocals != null) {
        this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    }
}

 可以发现构造函数只是定义了线程组信息和一些本线程信息,并且调用了ThreadLocal.createInheritedMap(parent.inheritableThreadLocals)

public class ThreadLocal<T> {
        static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
            return new ThreadLocalMap(parentMap);
        }
}
private ThreadLocalMap(ThreadLocalMap parentMap) {
    Entry[] parentTable = parentMap.table;
    int len = parentTable.length;
    setThreshold(len);
    table = new Entry[len];

    for (int j = 0; j < len; j++) {
        Entry e = parentTable[j];
        if (e != null) {
            @SuppressWarnings("unchecked")
            ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
            if (key != null) {
                Object value = key.childValue(e.value);
//为线程创建一个新的ThreadLocal Entry,用来存储线程和Looper
                Entry c = new Entry(key, value);
                int h = key.threadLocalHashCode & (len - 1);
                while (table[h] != null)
                    h = nextIndex(h, len);
                table[h] = c;
                size++;
            }
        }
    }
}

所以new一个线程的时候,创建了线程信息、线程组信息、ThreadLocal Entry。但是线程未真正的创建出来,也未启动。

我们接着看线程的启动 Thread.start()

public synchronized void start() {
   
    if (started)
        throw new IllegalThreadStateException();
    group.add(this);//把当前线程添加到线程组
    started = false;
    try {
        nativeCreate(this, stackSize, daemon);
        started = true;
    } finally {
        try {
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
            /* do nothing. If start0 threw a Throwable then
              it will be passed up the call stack */
        }
    }
}
nativeCreate是native方法,是实际创建线程的代码实现
private native static void nativeCreate(Thread t, long stackSize, boolean daemon);

C层实现在 /art/runtime/native/java_lang_Thread.cc 中

动态注册

     static JNINativeMethod gMethods[] = {
198    FAST_NATIVE_METHOD(Thread, currentThread, "()Ljava/lang/Thread;"),
199    FAST_NATIVE_METHOD(Thread, interrupted, "()Z"),
200    FAST_NATIVE_METHOD(Thread, isInterrupted, "()Z"),
201    NATIVE_METHOD(Thread, nativeCreate, "(Ljava/lang/Thread;JZ)V"),
202    NATIVE_METHOD(Thread, nativeGetStatus, "(Z)I"),
203    NATIVE_METHOD(Thread, holdsLock, "(Ljava/lang/Object;)Z"),
204    FAST_NATIVE_METHOD(Thread, interrupt0, "()V"),
205    NATIVE_METHOD(Thread, setNativeName, "(Ljava/lang/String;)V"),
206    NATIVE_METHOD(Thread, setPriority0, "(I)V"),
207    FAST_NATIVE_METHOD(Thread, sleep, "(Ljava/lang/Object;JI)V"),
208    NATIVE_METHOD(Thread, yield, "()V"),
209  };

NATIVE_METHOD是宏定义
#ifndef NATIVE_METHOD
21  #define NATIVE_METHOD(className, functionName, signature) \
22      { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
23  #endif

宏展开后得知方法名为Thread_nativeCreate

        static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size,
51                                  jboolean daemon) {
52            // There are sections in the zygote that forbid thread creation.
53            Runtime* runtime = Runtime::Current();
54            if (runtime->IsZygote() && runtime->IsZygoteNoThreadSection()) {//zygote进程禁用多线程
55                     jclass internal_error = env->FindClass("java/lang/InternalError");
56                      CHECK(internal_error != nullptr);
57                      env->ThrowNew(internal_error, "Cannot create threads in zygote");
58                      return;
59            }
60  
61            Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);
62  }

CreateNativeThread源码如下:

void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) {
823    CHECK(java_peer != nullptr);
824    Thread* self = static_cast<JNIEnvExt*>(env)->GetSelf();
825  
826    if (VLOG_IS_ON(threads)) {
827      ScopedObjectAccess soa(env);
828  
829      ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_name);
830      ObjPtr<mirror::String> java_name =
831          f->GetObject(soa.Decode<mirror::Object>(java_peer))->AsString();
832      std::string thread_name;
833      if (java_name != nullptr) {
834        thread_name = java_name->ToModifiedUtf8();
835      } else {
836        thread_name = "(Unnamed)";
837      }
838  
839      VLOG(threads) << "Creating native thread for " << thread_name;
840      self->Dump(LOG_STREAM(INFO));
841    }
842  
843    Runtime* runtime = Runtime::Current();
844  
845    // Atomically start the birth of the thread ensuring the runtime isn't shutting down.
846    bool thread_start_during_shutdown = false;
847    {
848      MutexLock mu(self, *Locks::runtime_shutdown_lock_);
849      if (runtime->IsShuttingDownLocked()) {
850        thread_start_during_shutdown = true;
851      } else {
852        runtime->StartThreadBirth();
853      }
854    }
855    if (thread_start_during_shutdown) {
856      ScopedLocalRef<jclass> error_class(env, env->FindClass("java/lang/InternalError"));
857      env->ThrowNew(error_class.get(), "Thread starting during runtime shutdown");
858      return;
859    }
860  //new一个C层的Thread
861    Thread* child_thread = new Thread(is_daemon);
862    // Use global JNI ref to hold peer live while child thread starts.
863    child_thread->tlsPtr_.jpeer = env->NewGlobalRef(java_peer);
864    stack_size = FixStackSize(stack_size);
868    env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
869                      reinterpret_cast<jlong>(child_thread));
873    std::string error_msg;
874    std::unique_ptr<JNIEnvExt> child_jni_env_ext(
875        JNIEnvExt::Create(child_thread, Runtime::Current()->GetJavaVM(), &error_msg));
876  
877    int pthread_create_result = 0;
878    if (child_jni_env_ext.get() != nullptr) {
879      pthread_t new_pthread;
880      pthread_attr_t attr;
881      child_thread->tlsPtr_.tmp_jni_env = child_jni_env_ext.get();
882      CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), "new thread");
883      CHECK_PTHREAD_CALL(pthread_attr_setdetachstate, (&attr, PTHREAD_CREATE_DETACHED),
884                         "PTHREAD_CREATE_DETACHED");
885      CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size);

            //实际上就是调用了C层的pthread_create
886      pthread_create_result = pthread_create(&new_pthread,
887                                             &attr,
888                                             Thread::CreateCallback,
889                                             child_thread);

890      CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread");
891  
892      if (pthread_create_result == 0) {
897        child_jni_env_ext.release();  // NOLINT pthreads API.
898        return;
899      }
900    }
903    {
904      MutexLock mu(self, *Locks::runtime_shutdown_lock_);
905      runtime->EndThreadBirth();
906    }
909    child_thread->DeleteJPeer(env);
910    delete child_thread;
911    child_thread = nullptr;
912    // TODO: remove from thread group?
913    env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
914    {
915      std::string msg(child_jni_env_ext.get() == nullptr ?
916          StringPrintf("Could not allocate JNI Env: %s", error_msg.c_str()) :
917          StringPrintf("pthread_create (%s stack) failed: %s",
918                                   PrettySize(stack_size).c_str(), strerror(pthread_create_result)));
919      ScopedObjectAccess soa(env);
920      soa.Self()->ThrowOutOfMemoryError(msg.c_str());
921    }
922  }

调用了C层的 pthread_create之后回调到了 Thread::CreateCallback

    void* Thread::CreateCallback(void* arg) {
597    Thread* self = reinterpret_cast<Thread*>(arg);
598    Runtime* runtime = Runtime::Current();
599    if (runtime == nullptr) {
600      LOG(ERROR) << "Thread attaching to non-existent runtime: " << *self;
601      return nullptr;
602    }
603    {
604      // TODO: pass self to MutexLock - requires self to equal Thread::Current(), which is only true
605      //       after self->Init().
606      MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
607      // Check that if we got here we cannot be shutting down (as shutdown should never have started
608      // while threads are being born).
609      CHECK(!runtime->IsShuttingDownLocked());
610      // Note: given that the JNIEnv is created in the parent thread, the only failure point here is
611      //       a mess in InitStackHwm. We do not have a reasonable way to recover from that, so abort
612      //       the runtime in such a case. In case this ever changes, we need to make sure here to
613      //       delete the tmp_jni_env, as we own it at this point.
614      CHECK(self->Init(runtime->GetThreadList(), runtime->GetJavaVM(), self->tlsPtr_.tmp_jni_env));
615      self->tlsPtr_.tmp_jni_env = nullptr;
616      Runtime::Current()->EndThreadBirth();
617    }
618    {
619      ScopedObjectAccess soa(self);
620      self->InitStringEntryPoints();
621  
622      // Copy peer into self, deleting global reference when done.
623      CHECK(self->tlsPtr_.jpeer != nullptr);
624      self->tlsPtr_.opeer = soa.Decode<mirror::Object>(self->tlsPtr_.jpeer).Ptr();
625      // Make sure nothing can observe both opeer and jpeer set at the same time.
626      self->DeleteJPeer(self->GetJniEnv());
627      self->SetThreadName(self->GetThreadName()->ToModifiedUtf8().c_str());
628  
629      ArtField* priorityField = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_priority);
630      self->SetNativePriority(priorityField->GetInt(self->tlsPtr_.opeer));
631  //Runtime执行线程启动完毕回调
632      runtime->GetRuntimeCallbacks()->ThreadStart(self);
633  
634      // Unpark ourselves if the java peer was unparked before it started (see
635      // b/28845097#comment49 for more information)
636  
637      ArtField* unparkedField = jni::DecodeArtField(
638          WellKnownClasses::java_lang_Thread_unparkedBeforeStart);
639      bool should_unpark = false;
640      {
641        // Hold the lock here, so that if another thread calls unpark before the thread starts
642        // we don't observe the unparkedBeforeStart field before the unparker writes to it,
643        // which could cause a lost unpark.
644        art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
645        should_unpark = unparkedField->GetBoolean(self->tlsPtr_.opeer) == JNI_TRUE;
646      }
647      if (should_unpark) {
648        self->Unpark();
649      }
650      // Invoke the 'run' method of our java.lang.Thread.
651      ObjPtr<mirror::Object> receiver = self->tlsPtr_.opeer;
652      jmethodID mid = WellKnownClasses::java_lang_Thread_run;
653      ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
654      InvokeVirtualOrInterfaceWithJValues(soa, ref.get(), mid, nullptr);
655    }
656    // Detach and delete self.
657    Runtime::Current()->GetThreadList()->Unregister(self);
658  
659    return nullptr;
660  }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闽农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值