« | August 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | | | | | |
| 公告 |
戒除浮躁,读好书,交益友 |
Blog信息 |
blog名称:邢红瑞的blog 日志总数:523 评论数量:1142 留言数量:0 访问次数:9694745 建立时间:2004年12月20日 |

| |
[jvm]java的线程实现 软件技术, 电脑与网络
邢红瑞 发表于 2007/5/26 15:45:24 |
java是一种平台无关的语言,但是他的线程实现确实平台相关的。绿色线程这是最简单的一种模型,操作系统对java thread毫不知晓,VM处理所有线程相关的东西,从操作系统的角度来说,它是单进程,单线程的程序。对于每一个线程,VM处理所有线程相关的东西,例如线程堆栈等等。VM负责线程上下文的切换,保存当前线程信息,加载线程,执行新的线程。在OS看来,VM模拟了多线程的环境,操作系统内核不知道多线程的存在。这就是绿色线程,也叫做用户线程,因为他们只存在用户级别的应用中。在大多数操作系统中,操作系统分为两层,用户级别和系统级别,用户级别的程序相对安全,他们不会造成操作系统的崩溃和影响其它应用,一个线程阻塞将使得整个进程(包括它的所有线程)阻塞。内核线程由操作系统直接支持。由操作系统内核创建、调度,内核维护进程及线程的上下文信息以及线程切换,一个内核线程由于I/O操作而阻塞,不会影响其它线程的运行。最早的java平台,使用绿色线程,现在大多数使用本地系统级别的线程。
运行这个程序public class ThreadTest {
public static void main(String[] args) { int nThreads = 10; long n = 89; Thread t[] = new Thread[nThreads];
for (int i = 0; i < t.length; i++) { t[i] = new Thread(new Task(n, "Task " + i)); t[i].start(); } for (int i = 0; i < t.length; i++) { try { t[i].join(); } catch (InterruptedException ie) {} } }}import java.util.*;import java.text.*;
public class Task implements Runnable { long n; String id;
private long fib(long n) { if (n == 0) return 0L; if (n == 1) return 1L; return fib(n - 1) + fib(n - 2); }
public Task(long n, String id) { this.n = n; this.id = id; }
public void run() { Date d = new Date(); DateFormat df = new SimpleDateFormat("HH:mm:ss:SSS"); long startTime = System.currentTimeMillis(); d.setTime(startTime); System.out.println("Starting task " + id + " at " + df.format(d)); fib(n); long endTime = System.currentTimeMillis(); d.setTime(endTime); System.out.println("Ending task " + id + " at " + df.format(d) + " after " + (endTime - startTime) + " milliseconds"); }}
windows本台,VM使用了系统线程,java线程和系统系统线程一对一的影射,java线程的调度依靠于windows操作系统。windows的线程优先级比较复杂,java线程的优先级从0到9,10个级别,不同虚拟机的实现可能不同。下面给出sun的jdk比较Java priority Win32 priority 0 THREAD_PRIORITY_IDLE 1 (Thread.MIN_PRIORITY) THREAD_PRIORITY_LOWEST 2 THREAD_PRIORITY_LOWEST 3 THREAD_PRIORITY_BELOW_NORMAL 4 THREAD_PRIORITY_BELOW_NORMAL 5 (Thread.NORM_PRIORITY) THREAD_PRIORITY_NORMAL 6 THREAD_PRIORITY_ABOVE_NORMAL 7 THREAD_PRIORITY_ABOVE_NORMAL 8 THREAD_PRIORITY_HIGHEST 9 THREAD_PRIORITY_HIGHEST 10 (Thread.MAX_PRIORITY) THREAD_PRIORITY_TIME_CRITICALwindows的运行结果Starting task Task 9 at 14:58:33:031Starting task Task 8 at 14:58:33:046Starting task Task 7 at 14:58:33:062Starting task Task 6 at 14:58:33:078Starting task Task 0 at 14:58:33:093Starting task Task 1 at 14:58:33:109Starting task Task 2 at 14:58:33:125Starting task Task 3 at 14:58:33:140Starting task Task 4 at 14:58:33:156Ending task Task 4 at 14:58:33:171 after 15 millisecondsEnding task Task 1 at 14:58:33:187 after 78 millisecondsStarting task Task 5 at 14:58:33:187Ending task Task 5 at 14:58:33:203 after 16 millisecondsEnding task Task 9 at 14:58:33:234 after 203 millisecondsEnding task Task 8 at 14:58:33:250 after 204 millisecondsEnding task Task 7 at 14:58:33:250 after 188 millisecondsEnding task Task 6 at 14:58:33:265 after 187 millisecondsEnding task Task 0 at 14:58:33:281 after 188 millisecondsEnding task Task 2 at 14:58:33:296 after 171 millisecondsEnding task Task 3 at 14:58:33:312 after 172 milliseconds可以发现高优先级的任务启动之前,低优先级的任务可以启动。mustang的源码// Allocate and initialize a new OSThreadbool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { unsigned thread_id;
// Allocate the OSThread object OSThread* osthread = new OSThread(NULL, NULL); if (osthread == NULL) { return false; }
// Initial state is ALLOCATED but not INITIALIZED { MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag); osthread->set_state(ALLOCATED); } // Initialize support for Java interrupts HANDLE interrupt_event = CreateEvent(NULL, true, false, NULL); if (interrupt_event == NULL) { delete osthread; return NULL; } osthread->set_interrupt_event(interrupt_event); osthread->set_interrupted(false); thread->set_osthread(osthread); if (stack_size == 0) { switch (thr_type) { case os::java_thread: // Java threads use ThreadStackSize which default value can be changed with the flag -Xss if (JavaThread::stack_size_at_create() > 0) stack_size = JavaThread::stack_size_at_create(); break; case os::compiler_thread: if (CompilerThreadStackSize > 0) { stack_size = (size_t)(CompilerThreadStackSize * K); break; } // else fall through: // use VMThreadStackSize if CompilerThreadStackSize is not defined case os::vm_thread: case os::pgc_thread: case os::cgc_thread: case os::watcher_thread: if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); break; } }
// Create the Win32 thread // // Contrary to what MSDN document says, "stack_size" in _beginthreadex() // does not specify stack size. Instead, it specifies the size of // initially committed space. The stack size is determined by // PE header in the executable. If the committed "stack_size" is larger // than default value in the PE header, the stack is rounded up to the // nearest multiple of 1MB. For example if the launcher has default // stack size of 320k, specifying any size less than 320k does not // affect the actual stack size at all, it only affects the initial // commitment. On the other hand, specifying 'stack_size' larger than // default value may cause significant increase in memory usage, because // not only the stack space will be rounded up to MB, but also the // entire space is committed upfront. // // Finally Windows XP added a new flag 'STACK_SIZE_PARAM_IS_A_RESERVATION' // for CreateThread() that can treat 'stack_size' as stack size. However we // are not supposed to call CreateThread() directly according to MSDN // document because JVM uses C runtime library. The good news is that the // flag appears to work with _beginthredex() as well.
#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION#define STACK_SIZE_PARAM_IS_A_RESERVATION (0x10000)#endif
HANDLE thread_handle = (HANDLE)_beginthreadex(NULL, (unsigned)stack_size, (unsigned (__stdcall *)(void*)) java_start, thread, CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id); if (thread_handle == NULL) { // perhaps STACK_SIZE_PARAM_IS_A_RESERVATION is not supported, try again // without the flag. thread_handle = (HANDLE)_beginthreadex(NULL, (unsigned)stack_size, (unsigned (__stdcall *)(void*)) java_start, thread, CREATE_SUSPENDED, &thread_id); } if (thread_handle == NULL) { // Need to clean up stuff we've allocated so far CloseHandle(osthread->interrupt_event()); thread->set_osthread(NULL); delete osthread; return NULL; } Atomic::inc_ptr((intptr_t*)&os::win32::_os_thread_count);
// Store info on the Win32 thread into the OSThread osthread->set_thread_handle(thread_handle); osthread->set_thread_id(thread_id);
// Initial thread state is INITIALIZED, not SUSPENDED { MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag); osthread->set_state(INITIALIZED); }
// The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain return true;}linux本地线程在jdk1.3以前的时代,linux完全使用green thread model,主要是内核不支持多线程并发,jdk1.3开始支持Linux native threads,使用ps可以看出不同进程的线程列表.从jdk 1.4.2开始,使用Native Posix Thread Library (NPTL)的Linux kernels,支持java和Linux kernels的线程一对一影射.mustang源码bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { assert(thread->osthread() == NULL, "caller responsible");
// Allocate the OSThread object OSThread* osthread = new OSThread(NULL, NULL); if (osthread == NULL) { return false; }
// set the correct thread state osthread->set_thread_type(thr_type);
// Initial state is ALLOCATED but not INITIALIZED osthread->set_state(ALLOCATED);
thread->set_osthread(osthread);
// init thread attributes pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// stack size if (os::Linux::supports_variable_stack_size()) { // calculate stack size if it's not specified by caller if (stack_size == 0) { stack_size = os::Linux::default_stack_size(thr_type);
switch (thr_type) { case os::java_thread: // Java threads use ThreadStackSize which default value can be changed with the flag -Xss if (JavaThread::stack_size_at_create() > 0) stack_size = JavaThread::stack_size_at_create(); break; case os::compiler_thread: if (CompilerThreadStackSize > 0) { stack_size = (size_t)(CompilerThreadStackSize * K); break; } // else fall through: // use VMThreadStackSize if CompilerThreadStackSize is not defined case os::vm_thread: case os::pgc_thread: case os::cgc_thread: case os::watcher_thread: if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); break; } }
stack_size = MAX2(stack_size, os::Linux::min_stack_allowed); pthread_attr_setstacksize(&attr, stack_size); } else { // let pthread_create() pick the default value. }
// glibc guard page pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));
ThreadState state;
{ // Serialize thread creation if we are running with fixed stack LinuxThreads bool lock = os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack(); if (lock) { os::Linux::createThread_lock()->lock_without_safepoint_check(); }
pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
pthread_attr_destroy(&attr);
if (ret != 0) { if (PrintMiscellaneous && (Verbose || WizardMode)) { perror("pthread_create()"); } // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; if (lock) os::Linux::createThread_lock()->unlock(); return false; }
// Store pthread info into the OSThread osthread->set_pthread_id(tid);
// Wait until child thread is either initialized or aborted { Monitor* sync_with_child = osthread->startThread_lock(); MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); while ((state = osthread->get_state()) == ALLOCATED) { sync_with_child->wait(Mutex::_no_safepoint_check_flag); } }
if (lock) { os::Linux::createThread_lock()->unlock(); } }
// Aborted due to thread limit being reached if (state == ZOMBIE) { thread->set_osthread(NULL); delete osthread; return false; }
// The thread is returned suspended (in state INITIALIZED), // and is started higher up in the call chain assert(state == INITIALIZED, "race condition"); return true;}可以看出使用pthread线程库,Linux 2.6内核的pthread实现为NPTL,NPTL 与它的前任相比优势在于 POSIX 兼容性和性能。在编译时可通过系统的头文件获取 POSIX 服务。可在运行时通过 libpthread.so 动态库和底层 Linux 核心支持获取 POSIX 服务。Linux 核心可以根据静态控制(如线程优先级级别)和系统中执行的线程的某些动态条件下来执行线程调度。soalris各个版本的实现,不大相同,就不详细说明了. |
|
回复:java的线程实现 软件技术, 电脑与网络
坏男孩(游客)发表评论于2007/6/12 22:24:27 |
|
» 1 »
|