private void init(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(); SecurityManager security = System.getSecurityManager(); if (g == null) { /* Determine if it's an applet or not */ /* If there is a security manager, ask the security manager what to do. */ // 如果是applet 则使用security的线程组 if (security != null) { g = security.getThreadGroup(); } /* If the security doesn't have a strong opinion of the matter use the parent thread group. */ // 如果线程组未指定,则使用当前线程的线程组 if (g == null) { g = parent.getThreadGroup(); } } /* checkAccess regardless of whether or not threadgroup is explicitly passed in. */ g.checkAccess();// 校验权限
/* * Do we have the required permissions? */ if (security != null) { if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } } // 线程组增加未启动的线程个数 g.addUnstarted(); this.group = g; this.daemon = parent.isDaemon();// 如果父线程是守护线程,则只能创建出来的线程默认也是守护线程 this.priority = parent.getPriority();// 优先级同父线程 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; setPriority(priority);// 设置优先级 if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize;
/* Set thread ID */ tid = nextThreadID();// 线程的id }
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) {// 如果线程存活则继续等待。 wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
// -XX:+PrintFlagsFinal -XX:MaxDirectMemorySize=512 // -XX:NativeMemoryTracking=detail -Xmx4g -Xss180k @Test public void stackSize() throws Exception { class Door { int deepNum;
public void openDoor() { deepNum++; if (deepNum < 10000) { openDoor(); } } } Door door = new Door(); Thread thread = new Thread(null, () -> { log.info("running..."); door.openDoor(); }, "xxxxxxx", 1024 * 512);
thread.start(); Field stackSizeField = Thread.class.getDeclaredField("stackSize"); stackSizeField.setAccessible(true); Object o = stackSizeField.get(thread); log.info("stackSize:" + s(o)); thread.join(); log.error("exp:{}", door.deepNum); }