4.2 启动和终止线程
4.2.1 构造线程
JDK1.8中java.lang.Thread类中的init方法源码:
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name.toCharArray();
//当前线程是该线程的父线程
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. */
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;
//将daemon、priority属性设置为父线程的对应属性
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);
// 继承父线程的inheritableThreadLocals
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* 分配一个线程ID */
tid = nextThreadID();
}
4.2.3 理解中断
中断可以理解为线程的一个标识位属性,它表示一个运行中的线程是否被其他线程进行了中断操作。
- isInterrupted:判断一个线程是否被中断,如果一个线程已经处于终结状态,即使之前这个线程被中断过,此时此刻调用该对象的isInterrupted方法返回的也是false.
Thread.interrupted():对当前线程的中断标识位进行复位。
/** * Tests whether the current thread has been interrupted. The * * <i>interrupted status</i> of the thread is cleared by this method. In * other words, if this method were to be called twice in succession, the * second call would return false (unless the current thread were * interrupted again, after the first call had cleared its interrupted * status and before the second call had examined it). * * <p>A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * * @return <code>true</code> if the current thread has been interrupted; * <code>false</code> otherwise. * @see #isInterrupted() * @revised 6.0 */ // 验证当前线程是否被中断过。对当前线程的中断标识位进行复位。换句话说,如果连续两次调用该方法,第二次调用时会返回false(除非是调用第一次后,调用第二次之前的时间空挡内又被中断过,会返回true) public static boolean interrupted() { return currentThread().isInterrupted(true); }
4.2.4 过期的suspend()、resume()和stop()
4.2.5 安全的终止线程
public class ShutDown{
private static class Runner implements Runnable{
private long i;
private volatile boolean on = true;
@Override
public void run(){
while(on && !Thread.currentThread().isInterrupted()){
i++;
}
System.out.println("Count i = " + i);
}
public void cancle(){
on = false;
}
}
public static void main(String[] args)throws Exception{
Runner one = new Runner();
Thread countThread = new Thread(one,"CountThread");
countThread.start();
//睡眠1秒,main线程对CountThread进行中断,使CountThread能够感知中断而结束
TimeUnit.SECONDES.sleep(1);
countThread.interrupt();
Runner two = new Runner();
countThread = new Thread(two,"CountThread");
countThread.start();
//睡眠1秒,main线程对Runner two 进行取消,使CountThread能够感知on为false而结束
TimeUnit.SECONDS.sleep(1);
two.cancel();
}
}
输出结果如下所示,可能会有所不同:
Count i = 543487324
Count i = 540898082
总结:main线程可以通过中断操作和cancel()方法均可使CountThread得以终止。