和很多其他编程语言一样,Java也支持多线程。对于不支持多线程的编程语言,在需要并发多任务处理的情况下,就相当困难了,尽管可能有其他的方式来实现。如lua,javascript等。
一个支持多线程编程的语言,这里以java为例,java线程和系统线程之间是怎么对应的,参考另一篇有关Java线程模型的文章:https://lobin.iteye.com/blog/630684。
Java通过java.lang.Thread描述一个线程。
Java Thread状态定义:
/** * A thread state. A thread can be in one of the following states: * <ul> * <li>{@link #NEW}<br> * A thread that has not yet started is in this state. * </li> * <li>{@link #RUNNABLE}<br> * A thread executing in the Java virtual machine is in this state. * </li> * <li>{@link #BLOCKED}<br> * A thread that is blocked waiting for a monitor lock * is in this state. * </li> * <li>{@link #WAITING}<br> * A thread that is waiting indefinitely for another thread to * perform a particular action is in this state. * </li> * <li>{@link #TIMED_WAITING}<br> * A thread that is waiting for another thread to perform an action * for up to a specified waiting time is in this state. * </li> * <li>{@link #TERMINATED}<br> * A thread that has exited is in this state. * </li> * </ul> * * <p> * A thread can be in only one state at a given point in time. * These states are virtual machine states which do not reflect * any operating system thread states. * * @since 1.5 * @see #getState */ public enum State { /** * Thread state for a thread which has not yet started. */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }
这些状态在JVM中对应的定义:参考hotspot\src\share\vm\prims\jvm.h中的定义。
/* * Java thread state support */ enum { JAVA_THREAD_STATE_NEW = 0, JAVA_THREAD_STATE_RUNNABLE = 1, JAVA_THREAD_STATE_BLOCKED = 2, JAVA_THREAD_STATE_WAITING = 3, JAVA_THREAD_STATE_TIMED_WAITING = 4, JAVA_THREAD_STATE_TERMINATED = 5, JAVA_THREAD_STATE_COUNT = 6 };
Java java.lang.Thread在JVM中java.lang.Thread对象的接口类java_lang_Thread参考hotspot\src\share\vm\classfile\javaClasses.hpp中的代码。
java_lang_Thread中的状态定义:
// Java Thread Status for JVMTI and M&M use. // This thread status info is saved in threadStatus field of // java.lang.Thread java class. enum ThreadStatus { NEW = 0, RUNNABLE = JVMTI_THREAD_STATE_ALIVE + // runnable / running JVMTI_THREAD_STATE_RUNNABLE, SLEEPING = JVMTI_THREAD_STATE_ALIVE + // Thread.sleep() JVMTI_THREAD_STATE_WAITING + JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT + JVMTI_THREAD_STATE_SLEEPING, IN_OBJECT_WAIT = JVMTI_THREAD_STATE_ALIVE + // Object.wait() JVMTI_THREAD_STATE_WAITING + JVMTI_THREAD_STATE_WAITING_INDEFINITELY + JVMTI_THREAD_STATE_IN_OBJECT_WAIT, IN_OBJECT_WAIT_TIMED = JVMTI_THREAD_STATE_ALIVE + // Object.wait(long) JVMTI_THREAD_STATE_WAITING + JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT + JVMTI_THREAD_STATE_IN_OBJECT_WAIT, PARKED = JVMTI_THREAD_STATE_ALIVE + // LockSupport.park() JVMTI_THREAD_STATE_WAITING + JVMTI_THREAD_STATE_WAITING_INDEFINITELY + JVMTI_THREAD_STATE_PARKED, PARKED_TIMED = JVMTI_THREAD_STATE_ALIVE + // LockSupport.park(long) JVMTI_THREAD_STATE_WAITING + JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT + JVMTI_THREAD_STATE_PARKED, BLOCKED_ON_MONITOR_ENTER = JVMTI_THREAD_STATE_ALIVE + // (re-)entering a synchronization block JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER, TERMINATED = JVMTI_THREAD_STATE_TERMINATED };
Java线程对象(java.lang.Thread线程对象)在Java对象内存模型中保存的线程状态就是ThreadStatus中定义的状态。
我们在java程序中获取线程状态,得到的Java Thread状态是根据和ThreadStatus对应关系得到的。对应关系如下,以sleep为例,从以下对应关系看出,我们看到的状态是TIMED_WAITING,这里很容易和wait,指定timeout时间时的情况混淆。
Java Thread中的状态和java_lang_Thread中的状态对应如下:
const char* java_lang_Thread::thread_status_name(oop java_thread) { assert(JDK_Version::is_gte_jdk15x_version() && _thread_status_offset != 0, "Must have thread status"); ThreadStatus status = (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset); switch (status) { case NEW : return "NEW"; case RUNNABLE : return "RUNNABLE"; case SLEEPING : return "TIMED_WAITING (sleeping)"; case IN_OBJECT_WAIT : return "WAITING (on object monitor)"; case IN_OBJECT_WAIT_TIMED : return "TIMED_WAITING (on object monitor)"; case PARKED : return "WAITING (parking)"; case PARKED_TIMED : return "TIMED_WAITING (parking)"; case BLOCKED_ON_MONITOR_ENTER : return "BLOCKED (on object monitor)"; case TERMINATED : return "TERMINATED"; default : return "UNKNOWN"; }; }
JVM中的各种线程继承体系
JVM中的各种线程
继承体系
JVM中OSThread、JavaThread、VMThread、WorkerThread的区别
线程函数的定义:
typedef void (*ThreadFunction)(JavaThread*, TRAPS);
OSThread
OSThread维护着OS相关的线程信息,它等同于JVM的sys_thread_t结构。
OSThread主要的代码在\hotspot\src\share\vm\runtime目录下的osThread.hpp和osThread.cpp
OSThread线程相关状态:ALLOCATED、INITIALIZED、RUNNABLE、MONITOR_WAIT、CONDVAR_WAIT、OBJECT_WAIT、BREAKPOINTED、SLEEPING、ZOMBIE。
具体参考ThreadState定义
enum ThreadState { ALLOCATED, // Memory has been allocated but not initialized INITIALIZED, // The thread has been initialized but yet started RUNNABLE, // Has been started and is runnable, but not necessarily running MONITOR_WAIT, // Waiting on a contended monitor lock CONDVAR_WAIT, // Waiting on a condition variable OBJECT_WAIT, // Waiting on an Object.wait() call BREAKPOINTED, // Suspended at breakpoint SLEEPING, // Thread.sleep() ZOMBIE // All done, but not reclaimed yet };
JavaThread
在JVM层面用来描述一个Java线程。Java通过java.lang.Thread来描述一个线程,如以下Java线程代码:
官方的一个例子:
class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; }
public void run() { // compute primes larger than minPrime . . . } } |
启动这个线程也很简单:
Thread t = new PrimeThread(); t.start(); |
JavaThread线程相关状态:参考hotspot\src\share\vm\utilities\globalDefinitions.hpp
enum JavaThreadState { _thread_uninitialized = 0, // should never happen (missing initialization) _thread_new = 2, // just starting up, i.e., in process of being initialized _thread_new_trans = 3, // corresponding transition state (not used, included for completness) _thread_in_native = 4, // running in native code _thread_in_native_trans = 5, // corresponding transition state _thread_in_vm = 6, // running in VM _thread_in_vm_trans = 7, // corresponding transition state _thread_in_Java = 8, // running in Java or in stub code _thread_in_Java_trans = 9, // corresponding transition state (not used, included for completness) _thread_blocked = 10, // blocked in vm _thread_blocked_trans = 11, // corresponding transition state _thread_max_state = 12 // maximum thread state+1 - used for statistics allocation };
Java线程启动执行时,java.lang.Thread中run方法就是线程执行的代码。我们知道,在编写C/C++多线程程序时,在创建一个线程时,会传入一个线程函数。这里java.lang.Thread中run方法就相当于线程函数的实现。Java程序在运行时,JVM中有一个thread_entry函数用于表示Java线程的执行入口run方法。
线程函数:
static void thread_entry(JavaThread* thread, TRAPS) { HandleMark hm(THREAD); Handle obj(THREAD, thread->threadObj()); JavaValue result(T_VOID); JavaCalls::call_virtual(&result, obj, KlassHandle(THREAD, SystemDictionary::Thread_klass()), vmSymbols::run_method_name(), vmSymbols::void_method_signature(), THREAD); }
Java线程在启动时, 即调用start方法启动一个java线程,将调用start0方法进行启动,该方法是一个native方法,即进入jvm执行,对应JVM_StartThread函数,在JVM层面,就是通过创建一个JavaThread来启动运行,这个时候会创建一个native thread,即new JavaThread(&thread_entry, sz),其第一个参数为线程函数,第二个参数表示线程对应的栈大小,这里传入的是java.lang.Thread#stackSize的值,但这个值通常为0,所以栈大小取决于vm。
其中SystemDictionary::Thread_klass()需要展开宏才能开出来:
static klassOop Thread_klass() { return check_klass_Pre(_well_known_klasses[Thread_klass_knum]); }
在创建JavaThread时,会调用os::create_thread函数,并传入创建的JavaThread线程对象,以及线程类型ThreadType.java_thread, 以及前面的栈大小,在os::create_thread函数中,会为JavaThread线程分配一个对应的OSThread,再调用pthread_create启动一个线程,在启动这个线程时,传入的线程函数为java_start,线程传入的参数为前面创建的JavaThread线程。
pthread_create线程函数:java_start
// Thread start routine for all newly created threads static void *java_start(Thread *thread) { // Try to randomize the cache line index of hot stack frames. // This helps when threads of the same stack traces evict each other's // cache lines. The threads can be either from the same JVM instance, or // from different JVM instances. The benefit is especially true for // processors with hyperthreading technology. static int counter = 0; int pid = os::current_process_id(); alloca(((pid ^ counter++) & 7) * 128); ThreadLocalStorage::set_thread(thread); OSThread* osthread = thread->osthread(); Monitor* sync = osthread->startThread_lock(); // non floating stack LinuxThreads needs extra check, see above if (!_thread_safety_check(thread)) { // notify parent thread MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); osthread->set_state(ZOMBIE); sync->notify_all(); return NULL; } // thread_id is kernel thread id (similar to Solaris LWP id) osthread->set_thread_id(os::Linux::gettid()); if (UseNUMA) { int lgrp_id = os::numa_get_group_id(); if (lgrp_id != -1) { thread->set_lgrp_id(lgrp_id); } } // initialize signal mask for this thread os::Linux::hotspot_sigmask(thread); // initialize floating point control register os::Linux::init_thread_fpu_state(); // handshaking with parent thread { MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); // notify parent thread osthread->set_state(INITIALIZED); sync->notify_all(); // wait until os::start_thread() while (osthread->get_state() == INITIALIZED) { sync->wait(Mutex::_no_safepoint_check_flag); } } // call one more level start routine thread->run(); return 0; }
在java_start线程函数中会调用JavaThread的run方法:
// The first routine called by a new Java thread void JavaThread::run() { // initialize thread-local alloc buffer related fields this->initialize_tlab(); // used to test validitity of stack trace backs this->record_base_of_stack_pointer(); // Record real stack base and size. this->record_stack_base_and_size(); // Initialize thread local storage; set before calling MutexLocker this->initialize_thread_local_storage(); this->create_stack_guard_pages(); this->cache_global_variables(); // Thread is now sufficient initialized to be handled by the safepoint code as being // in the VM. Change thread state from _thread_new to _thread_in_vm ThreadStateTransition::transition_and_fence(this, _thread_new, _thread_in_vm); assert(JavaThread::current() == this, "sanity check"); assert(!Thread::current()->owns_locks(), "sanity check"); DTRACE_THREAD_PROBE(start, this); // This operation might block. We call that after all safepoint checks for a new thread has // been completed. this->set_active_handles(JNIHandleBlock::allocate_block()); if (JvmtiExport::should_post_thread_life()) { JvmtiExport::post_thread_start(this); } EVENT_BEGIN(TraceEventThreadStart, event); EVENT_COMMIT(event, EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(this->threadObj()))); // We call another function to do the rest so we are sure that the stack addresses used // from there will be lower than the stack base just computed thread_main_inner(); // Note, thread is no longer valid at this point! }
这里最后调用了一个thread_main_inner函数:
void JavaThread::thread_main_inner() { assert(JavaThread::current() == this, "sanity check"); assert(this->threadObj() != NULL, "just checking"); // Execute thread entry point unless this thread has a pending exception // or has been stopped before starting. // Note: Due to JVM_StopThread we can have pending exceptions already! if (!this->has_pending_exception() && !java_lang_Thread::is_stillborn(this->threadObj())) { { ResourceMark rm(this); this->set_native_thread_name(this->get_thread_name()); } HandleMark hm(this); this->entry_point()(this, this); } DTRACE_THREAD_PROBE(stop, this); this->exit(false); delete this; }
其中调用了线程函数:this->entry_point()(this, this);这里的线程函数就是之前创建JavaThread时传入的entry point,即ThreadFunction,也就是调用thread_entry函数。
在thread_entry函数中,会调用JavaCalls::call_virtual函数,这之后又回到java,这里后面将执行java程序编译后的字节码,即java.lang.Thread#run()方法编译后的字节码。
VMThread
VMThread表示原始线程,用于孵化其他所有线程,其他线程也用它来卸载一些VM重操作,如内存清理、垃圾回收等。主要代码在hotspot\src\share\vm\runtime目录下的vmThread.hpp和vmThread.cpp。
WorkerThread
工作线程,继承至NamedThread,可以指定一个命名标识,以及一个id来标识关联的线程执行的工作。
相关推荐
"Java-基础/jvm/多线程"这个主题涵盖了Java语言的基础知识,包括JVM(Java虚拟机)、多线程以及Java的基础语法和特性。 1. **JVM、JRE和JDK的关系**: - JVM(Java Virtual Machine)是Java程序运行的平台,负责...
Java面试中的JVM(Java虚拟机)和多线程是两个关键的知识领域,对于求职者来说,掌握这两点能够显著提升面试成功率。JVM是Java程序的运行平台,它负责解释执行字节码,实现跨平台运行。多线程则是Java编程中实现并发...
本文将根据提供的文件信息,对JAVA基础、集合类、JVM、IO/NIO、多线程以及Spring框架的基本原理进行深入解析,旨在帮助读者全面理解这些核心概念。 #### 1. Java基础 Java语言的基础部分包括了变量、数据类型、...
在Java中,实现多线程有两种主要方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当我们创建一个新的类,让它继承Thread类时,可以通过重写`run()`方法来定义线程执行的任务。然后创建该类的对象,并...
Java进阶学习教程中的第13章主要涵盖了JVM(Java虚拟机)和多线程两个核心概念。JVM是Java程序运行的基础,它负责解释执行字节码文件,并提供了Java语言的跨平台特性。Java程序通过JVM与操作系统交互,使得程序可以...
Java中的IO(输入/输出)和线程是两个核心概念,它们在开发高效、响应性强的应用程序时起着至关重要的作用。输入/输出处理数据的传输,而多线程则涉及程序的并发执行。 首先,让我们深入理解Java的IO系统。Java.IO...
本文档的主要目标是研究Java虚拟机(JVM)的工作原理及其设计背后的原因,而非深入探讨Java语言本身。我们将关注于机器如何运作,并且更重要的是,探究JVM开发者为何选择特定的方式来设计这些功能。 #### 为什么...
### JAVA JVM原理资料知识点 #### 一、语言处理器的基本结构 **语言处理器**是指能够处理某种编程语言的工具,常见的包括编译器、解释器、IDE等。 1. **编译器的基本结构**: - **词法分析器**:将源代码分割成...
在Java中,每个Java虚拟机(JVM)实例都有一个主线程,可以通过创建额外的线程来执行并发任务。 2. **线程的创建** - Java提供了多种创建线程的方式,如通过实现Runnable接口或继承Thread类。推荐使用实现...
Java的多线程是其编程语言中的一个重要特性,允许在单个程序中同时执行多个任务,从而提高程序的效率和响应性。理解多线程对于Java开发者至关重要,尤其对初学者来说,是掌握高级编程技巧的基础。 首先,我们需要...
在Java中,线程的创建可以通过继承`Thread`类或实现`Runnable`接口。线程的主体行为定义在`run()`方法中,当`start()`方法被调用时,线程进入可运行态,系统会根据线程调度策略来决定何时执行线程。线程的状态包括新...
Java多线程是Java编程中一个重要的概念,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要分为两种实现方式:通过子类化Thread类和实现Runnable接口。 1. 子类化Thread类: 当...
在Java中创建线程主要有两种方式:继承`Thread`类或者实现`Runnable`接口。在这个场景下,我们可能创建了两个类,一个是`WriterThread`用于写入成绩,另一个是`ReaderThread`用于读取并显示成绩。 在写入线程(`...
Java线程是多任务编程的重要概念,特别是在Java这种支持并发执行的高级编程语言中。Java线程允许程序同时执行多个独立的代码段,这极大地提高了程序的效率和响应性。以下是对Java线程入门的详细讲解: 1. **线程的...
在Java编程语言中,线程是程序执行的基本单元,它允许程序同时执行多个任务。创建一个单线程在Java中非常常见,特别是在处理并发问题时。这个实例将帮助初学者理解如何在Java中创建和管理单线程。下面我们将详细讨论...
在Java中,可以通过实现Runnable接口或继承Thread类来创建线程。创建后,调用start()方法启动线程,而非run()方法,因为start()会触发Java虚拟机(JVM)执行线程的run()方法。 其次,线程同步是多线程编程中的关键...
在Java编程中,多线程是程序设计中的一个重要概念,特别是在服务器端应用和高并发场景下,多线程能够充分利用CPU资源,提高程序的执行效率。本知识点将深入探讨Java多线程编程模板,帮助开发者理解和掌握如何在Java...
Java虚拟机(JVM)为每一个Java应用程序启动一个进程,而在这个进程中,所有的代码执行都是通过线程来完成的。默认情况下,Java程序的main方法在一个称为主线程的线程中运行。当main方法执行完毕,主线程结束,JVM...
在Java中,线程是进程中的一个执行单元,每个进程至少包含一个线程,通常Java虚拟机(JVM)启动时会创建一个进程,即java.exe,其中包含主线程,主要执行main方法。除此之外,还有垃圾回收线程等后台线程在运行。 ...
在深入探讨JVM(Java虚拟机)的特性之前,我们首先需要了解Java虚拟机在整个Java体系中所扮演的角色。Java虚拟机是运行Java字节码的抽象计算机,它使得Java语言具有“一次编写,到处运行”的特性。JVM的特性不但支撑...