/** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (null, null, gname)}, where {@code gname} is a newly generated * name. Automatically generated names are of the form * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. */ publicThread() { this(null, null, "Thread-" + nextThreadNum(), 0); }
/** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (null, target, gname)}, where {@code gname} is a newly generated * name. Automatically generated names are of the form * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. * * @param target * the object whose {@code run} method is invoked when this thread * is started. If {@code null}, this classes {@code run} method does * nothing. */ publicThread(Runnable target) { this(null, target, "Thread-" + nextThreadNum(), 0); }
/** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (group, target, gname)} ,where {@code gname} is a newly generated * name. Automatically generated names are of the form * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer. * * @param group * the thread group. If {@code null} and there is a security * manager, the group is determined by {@linkplain * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. * If there is not a security manager or {@code * SecurityManager.getThreadGroup()} returns {@code null}, the group * is set to the current thread's thread group. * * @param target * the object whose {@code run} method is invoked when this thread * is started. If {@code null}, this thread's run method is invoked. * * @throws SecurityException * if the current thread cannot create a thread in the specified * thread group */ publicThread(ThreadGroup group, Runnable target) { this(group, target, "Thread-" + nextThreadNum(), 0); }
/** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (null, null, name)}. * * @param name * the name of the new thread */ publicThread(String name) { this(null, null, name, 0); } /** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (group, null, name)}. * * @param group * the thread group. If {@code null} and there is a security * manager, the group is determined by {@linkplain * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. * If there is not a security manager or {@code * SecurityManager.getThreadGroup()} returns {@code null}, the group * is set to the current thread's thread group. * * @param name * the name of the new thread * * @throws SecurityException * if the current thread cannot create a thread in the specified * thread group */ publicThread(ThreadGroup group, String name) { this(group, null, name, 0); }
/** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (null, target, name)}. * * @param target * the object whose {@code run} method is invoked when this thread * is started. If {@code null}, this thread's run method is invoked. * * @param name * the name of the new thread */ publicThread(Runnable target, String name) { this(null, target, name, 0); }
/** * * @param group * the thread group. If {@code null} and there is a security * manager, the group is determined by {@linkplain * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}. * If there is not a security manager or {@code * SecurityManager.getThreadGroup()} returns {@code null}, the group * is set to the current thread's thread group. * * @param target * the object whose {@code run} method is invoked when this thread * is started. If {@code null}, this thread's run method is invoked. * * @param name * the name of the new thread * * @throws SecurityException * if the current thread cannot create a thread in the specified * thread group or cannot override the context class loader methods. */ publicThread(ThreadGroup group, Runnable target, String name) { this(group, target, name, 0); }
/** * Changes the name of this thread to be equal to the argument {@code name}. * <p> * First the {@code checkAccess} method of this thread is called * with no arguments. This may result in throwing a * {@code SecurityException}. * * @param name the new name for this thread. * @throws SecurityException if the current thread cannot modify this * thread. * @see #getName * @see #checkAccess() */ publicfinalsynchronizedvoidsetName(String name) { checkAccess(); if (name == null) { thrownewNullPointerException("name cannot be null"); }
/** * Initializes a Thread. * * @param g the Thread group * @param target the object whose run() method gets called * @param name the name of the new Thread * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. * @param acc the AccessControlContext to inherit, or * AccessController.getContext() if null * @param inheritThreadLocals if {@code true}, inherit initial values for * inheritable thread-locals from the constructing thread */ @SuppressWarnings("removal") privateThread(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { if (name == null) { thrownewNullPointerException("name cannot be null"); }
this.name = name;
Threadparent= currentThread(); // 调用获取当前线程函数 SecurityManagersecurity= 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. */ if (security != null) { g = security.getThreadGroup(); }
/* If the security manager doesn't have a strong opinion on 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( SecurityConstants.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;
Threadparent= currentThread(); // 调用获取当前线程函数 SecurityManagersecurity= 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. */ if (security != null) { g = security.getThreadGroup(); }
/* If the security manager doesn't have a strong opinion on 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( SecurityConstants.SUBCLASS_IMPLEMENTATION_PERMISSION); } }
/** * 测试 Thread 与 ThreadGroup */ publicclassThreadGroupTest { publicstaticvoidmain(String[] args) { Threadt1=newThread("t1"); ThreadGroupgroup=newThreadGroup("group1"); Threadt2=newThread(group,"t2"); ThreadGroupmainThreadGroup= Thread.currentThread().getThreadGroup(); System.out.println("Main thread belong group:"+ mainThreadGroup.getName()); System.out.println("tl and main belong the same group:" + (mainThreadGroup== t1.getThreadGroup())); System.out.println("t2 thread group not belong main group:" + (mainThreadGroup== t2.getThreadGroup())); System.out.println("t2 thread group belong main TestGroup:" + (group == t2.getThreadGroup())); } }
输出结果如下:
1 2 3 4
Main thread belong group:main tl and main belong the same group:true t2 thread group not belong main group:false t2 thread group belong main TestGroup:true
Thread与stack size
在Thread的构造函数中有一个stackSize参数,说明内容为the desired stack size for the new thread, or zero to indicate that this parameter is to be ignored.。翻译过来的意思是stackSize指的是新线程栈的大小,可以传0代表忽略这个参数而使用默认的栈内存大小。栈内存大小这块内容是与JVM配置栈大小相关的。下面基于此分析。
The stack size is the approximate number of bytes of address space that the virtual machine is to allocate for this thread's stack. The effect of the stackSize parameter, if any, is highly platform dependent.
On some platforms, specifying a higher value for the stackSize parameter may allow a thread to achieve greater recursion depth before throwing a StackOverflowError. Similarly, specifying a lower value may allow a greater number of threads to exist concurrently without throwing an OutOfMemoryError (or other internal error). The details of the relationship between the value of the stackSize parameter and the maximum recursion depth and concurrency level are platform-dependent. On some platforms, the value of the stackSize parameter may have no effect whatsoever.
The virtual machine is free to treat the stackSize parameter as a suggestion. If the specified value is unreasonably low for the platform, the virtual machine may instead use some platform-specific minimum value; if the specified value is unreasonably high, the virtual machine may instead use some platform-specific maximum. Likewise, the virtual machine is free to round the specified value up or down as it sees fit (or to ignore it completely).
Specifying a value of zero for the stackSize parameter will cause this constructor to behave exactly like the Thread(ThreadGroup, Runnable, String) constructor.
Due to the platform-dependent nature of the behavior of this constructor, extreme care should be exercised in its use. The thread stack size necessary to perform a given computation will likely vary from one JRE implementation to another. In light of this variation, careful tuning of the stack size parameter may be required, and the tuning may need to be repeated for each JRE implementation on which an application is to run.
Implementation note: Java platform implementers are encouraged to document their implementation's behavior with respect to the stackSize parameter.