本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
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各个版本的实现,不大相同,就不详细说明了.


阅读全文(10590) | 回复(1) | 编辑 | 精华
 


回复:java的线程实现
软件技术,  电脑与网络

坏男孩(游客)发表评论于2007/6/12 22:24:27

找个跟踪线程执行的软家有没有


个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 


» 1 »

发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.063 second(s), page refreshed 144769739 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号