JAVA线程启动时间的问题。。。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA线程启动时间的问题。。。相关的知识,希望对你有一定的参考价值。

程序运行以后,需要一个线程每天固定时间启动(比如说两点钟)。

不知道就这么一直让线程休眠上24小时执行一次好不好?

还有,非常急切的问题。第一次运行的时间怎么确定?除了一直判断时间直到正确的时候,还有没有其他更好的办法?

使用Timer和Timertask,可以设定在什么时候自动运行。
Timer有个scheduleAtFixedRate(TimerTask task, Date firstTime, long period) 方法,可以firstTime设置城下一个你要执行的时间,将period设置为24小时,这样就实现了固定时间执行程序的功能
参考技术A 第一次运行的扑捉系统时间 参考技术B linux 建议你 crontab 定时执行
windows 计划任务

否则. 每1分钟判断一次时间. 如果符合时间片则执行. 否则. sleep一分钟
参考技术C 用JAVA的TIMER类可以实现定时每天两点执行。 参考技术D 这个需求可以使用定时任务。查查这方面的资料。

java.lang.InternalError 线程在运行时关闭期间启动

【中文标题】java.lang.InternalError 线程在运行时关闭期间启动【英文标题】:java.lang.InternalError Thread starting during runtime shutdown 【发布时间】:2016-04-15 17:18:53 【问题描述】:

我们无法获得此异常的确切原因。有谁知道,为什么这个异常发生在android应用程序中?提前致谢。

这是 Exception 的完整堆栈跟踪:

Fatal Exception: java.lang.InternalError: Thread starting during runtime shutdown
       at java.lang.Thread.nativeCreate(Thread.java)
       at java.lang.Thread.start(Thread.java:1063)
       at org.apache.http.impl.conn.tsccm.AbstractConnPool.enableConnectionGC(AbstractConnPool.java:145)
       at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.createConnectionPool(ThreadSafeClientConnManager.java:125)
       at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.<init>(ThreadSafeClientConnManager.java:103)
       at org.acra.util.HttpRequest.getHttpClient(HttpRequest.java:214)
       at org.acra.util.HttpRequest.send(HttpRequest.java:141)
       at org.acra.sender.HttpSender.send(HttpSender.java:225)
       at org.acra.SendWorker.sendCrashReport(SendWorker.java:179)
       at org.acra.SendWorker.checkAndSendReports(SendWorker.java:141)
       at org.acra.SendWorker.run(SendWorker.java:77)

【问题讨论】:

写完整的调用栈跟踪。 这不是 ANR。应用程序在特定屏幕上崩溃。 github.com/ACRA/acra/issues/196 【参考方案1】:
void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) 
  CHECK(java_peer != nullptr);
  Thread* self = static_cast<JNIEnvExt*>(env)->self;

  if (VLOG_IS_ON(threads)) 
    ScopedObjectAccess soa(env);

    ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name);
    mirror::String* java_name = reinterpret_cast<mirror::String*>(f->GetObject(
        soa.Decode<mirror::Object*>(java_peer)));
    std::string thread_name;
    if (java_name != nullptr) 
      thread_name = java_name->ToModifiedUtf8();
     else 
      thread_name = "(Unnamed)";
    

    VLOG(threads) << "Creating native thread for " << thread_name;
    self->Dump(LOG(INFO));
  

  Runtime* runtime = Runtime::Current();

  // Atomically start the birth of the thread ensuring the runtime isn't shutting down.
  bool thread_start_during_shutdown = false;
  
    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
    if (runtime->IsShuttingDownLocked()) 
      thread_start_during_shutdown = true;
     else 
      runtime->StartThreadBirth();
    
  
  if (thread_start_during_shutdown) //At there!!!
    ScopedLocalRef<jclass> error_class(env, env->FindClass("java/lang/InternalError"));
    env->ThrowNew(error_class.get(), "Thread starting during runtime shutdown");
    return;
  

  Thread* child_thread = new Thread(is_daemon);
  // Use global JNI ref to hold peer live while child thread starts.
  child_thread->tlsPtr_.jpeer = env->NewGlobalRef(java_peer);
  stack_size = FixStackSize(stack_size);

  // Thread.start is synchronized, so we know that nativePeer is 0, and know that we're not racing to
  // assign it.
  env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
                    reinterpret_cast<jlong>(child_thread));

  // Try to allocate a JNIEnvExt for the thread. We do this here as we might be out of memory and
  // do not have a good way to report this on the child's side.
  std::unique_ptr<JNIEnvExt> child_jni_env_ext(
      JNIEnvExt::Create(child_thread, Runtime::Current()->GetJavaVM()));

  int pthread_create_result = 0;
  if (child_jni_env_ext.get() != nullptr) 
    pthread_t new_pthread;
    pthread_attr_t attr;
    child_thread->tlsPtr_.tmp_jni_env = child_jni_env_ext.get();
    CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), "new thread");
    CHECK_PTHREAD_CALL(pthread_attr_setdetachstate, (&attr, PTHREAD_CREATE_DETACHED),
                       "PTHREAD_CREATE_DETACHED");
    CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size);
    pthread_create_result = pthread_create(&new_pthread,
                                           &attr,
                                           Thread::CreateCallback,
                                           child_thread);
    CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread");

    if (pthread_create_result == 0) 
      // pthread_create started the new thread. The child is now responsible for managing the
      // JNIEnvExt we created.
      // Note: we can't check for tmp_jni_env == nullptr, as that would require synchronization
      //       between the threads.
      child_jni_env_ext.release();
      return;
    
  

  // Either JNIEnvExt::Create or pthread_create(3) failed, so clean up.
  
    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
    runtime->EndThreadBirth();
  
  // Manually delete the global reference since Thread::Init will not have been run.
  env->DeleteGlobalRef(child_thread->tlsPtr_.jpeer);
  child_thread->tlsPtr_.jpeer = nullptr;
  delete child_thread;
  child_thread = nullptr;
  // TODO: remove from thread group?
  env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
  
    std::string msg(child_jni_env_ext.get() == nullptr ?
        "Could not allocate JNI Env" :
        StringPrintf("pthread_create (%s stack) failed: %s",
                                 PrettySize(stack_size).c_str(), strerror(pthread_create_result)));
    ScopedObjectAccess soa(env);
    soa.Self()->ThrowOutOfMemoryError(msg.c_str());
  

【讨论】:

你不觉得解释会更好

以上是关于JAVA线程启动时间的问题。。。的主要内容,如果未能解决你的问题,请参考以下文章

如何验证线程中的命令是不是在Java中成功启动并且可以启动另一个线程?

在java中不使用join()一个接一个地启动线程

如何创建和启动一个线程

java.lang.InternalError 线程在运行时关闭期间启动

线程“主”java.lang.NoClassDefFoundError 中的异常:启动 pyspark 时

JAVA面试题 启动线程是start()还是run()?为什么?