【高并发】朋友去面试竟然栽在了Thread类的源码上

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"大家好,我是冰河~~","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最近和一个朋友聊天,他跟我说起了他去XXX公司面试的情况,面试官的一个问题把他打懵了!竟然问他:你经常使用Thread创建线程,那你看过Thread类的源码吗?我这个朋友自然是没看过Thread类的源码,然后,就没有然后了!!!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以,我们学习技术不仅需要知其然,更需要知其所以然,今天,我们就一起来简单看看Thread类的源码。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"注意:本文是基于JDK 1.8来进行分析的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Thread类的继承关系","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们可以使用下图来表示Thread类的继承关系。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/df/df4fb4aca69944039b1fd0a74b6a6abb.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由上图我们可以看出,Thread类实现了Runnable接口,而Runnable在JDK 1.8中被@FunctionalInterface注解标记为函数式接口,Runnable接口在JDK 1.8中的源代码如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@FunctionalInterface\npublic interface Runnable {\n public abstract void run();\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Runnable接口的源码比较简单,只是提供了一个run()方法,这里就不再赘述了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下来,我们再来看看@FunctionalInterface注解的源码,如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Documented\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface FunctionalInterface {}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到,@FunctionalInterface注解声明标记在Java类上,并在程序运行时生效。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Thread类的源码剖析","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Thread类定义","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Thread在java.lang包下,Thread类的定义如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class Thread implements Runnable {\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"加载本地资源","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"打开Thread类后,首先,我们会看到在Thread类的最开始部分,定义了一个静态本地方法registerNatives(),这个方法主要用来注册一些本地系统的资源。并在静态代码块中调用这个本地方法,如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"//定义registerNatives()本地方法注册系统资源\nprivate static native void registerNatives();\nstatic {\n //在静态代码块中调用注册本地系统资源的方法\n registerNatives();\n}\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Thread中的成员变量","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Thread类中的成员变量如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"//当前线程的名称\nprivate volatile String name;\n//线程的优先级\nprivate int priority;\nprivate Thread threadQ;\nprivate long eetop;\n//当前线程是否是单步线程\nprivate boolean single_step;\n//当前线程是否在后台运行\nprivate boolean daemon = false;\n//Java虚拟机的状态\nprivate boolean stillborn = false;\n//真正在线程中执行的任务\nprivate Runnable target;\n//当前线程所在的线程组\nprivate ThreadGroup group;\n//当前线程的类加载器\nprivate ClassLoader contextClassLoader;\n//访问控制上下文\nprivate AccessControlContext inheritedAccessControlContext;\n//为匿名线程生成名称的编号\nprivate static int threadInitNumber;\n//与此线程相关的ThreadLocal,这个Map维护的是ThreadLocal类\nThreadLocal.ThreadLocalMap threadLocals = null;\n//与此线程相关的ThreadLocal\nThreadLocal.ThreadLocalMap inheritableThreadLocals = null;\n//当前线程请求的堆栈大小,如果未指定堆栈大小,则会交给JVM来处理\nprivate long stackSize;\n//线程终止后存在的JVM私有状态\nprivate long nativeParkEventPointer;\n//线程的id\nprivate long tid;\n//用于生成线程id\nprivate static long threadSeqNumber;\n//当前线程的状态,初始化为0,代表当前线程还未启动\nprivate volatile int threadStatus = 0;\n//由(私有)java.util.concurrent.locks.LockSupport.setBlocker设置\n//使用java.util.concurrent.locks.LockSupport.getBlocker访问\nvolatile Object parkBlocker;\n//Interruptible接口中定义了interrupt方法,用来中断指定的线程\nprivate volatile Interruptible blocker;\n//当前线程的内部锁\nprivate final Object blockerLock = new Object();\n//线程拥有的最小优先级\npublic final static int MIN_PRIORITY = 1;\n//线程拥有的默认优先级\npublic final static int NORM_PRIORITY = 5;\n//线程拥有的最大优先级\npublic final static int MAX_PRIORITY = 10;\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从Thread类的成员变量,我们可以看出,Thread类本质上不是一个任务,它是一个实实在在的线程对象,在Thread类中拥有一个Runnable类型的成员变量target,而这个target成员变量就是需要在Thread线程对象中执行的任务。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"线程的状态定义","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Thread类的内部,定义了一个枚举State,如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public enum State {\n //初始化状态\n NEW,\n //可运行状态,此时的可运行包括运行中的状态和就绪状态\n RUNNABLE,\n //线程阻塞状态\n BLOCKED,\n //等待状态\n WAITING,\n //超时等待状态\n TIMED_WAITING,\n //线程终止状态\n TERMINATED;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这个枚举类中的状态就代表了线程生命周期的各状态。我们可以使用下图来表示线程各个状态之间的转化关系。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/18/18a7187119ae64456205521106a3e194.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"NEW:初始状态,线程被构建,但是还没有调用start()方法。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"RUNNABLE:可运行状态,可运行状态可以包括:运行中状态和就绪状态。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BLOCKED:阻塞状态,处于这个状态的线程需要等待其他线程释放锁或者等待进入synchronized。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"WAITING:表示等待状态,处于该状态的线程需要等待其他线程对其进行通知或中断等操作,进而进入下一个状态。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TIME_WAITING:超时等待状态。可以在一定的时间自行返回。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TERMINATED:终止状态,当前线程执行完毕。","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Thread类的构造方法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Thread类中的所有构造方法如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public Thread() {\n init(null, null, \"Thread-\" + nextThreadNum(), 0);\n}\npublic Thread(Runnable target) {\n init(null, target, \"Thread-\" + nextThreadNum(), 0);\n}\nThread(Runnable target, AccessControlContext acc) {\n init(null, target, \"Thread-\" + nextThreadNum(), 0, acc, false);\n}\npublic Thread(ThreadGroup group, Runnable target) {\n init(group, target, \"Thread-\" + nextThreadNum(), 0);\n}\npublic Thread(String name) {\n init(null, null, name, 0);\n}\npublic Thread(ThreadGroup group, String name) {\n init(group, null, name, 0);\n}\npublic Thread(Runnable target, String name) {\n init(null, target, name, 0);\n}\npublic Thread(ThreadGroup group, Runnable target, String name) {\n init(group, target, name, 0);\n}\npublic Thread(ThreadGroup group, Runnable target, String name,\n long stackSize) {\n init(group, target, name, stackSize);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其中,我们最经常使用的就是如下几个构造方法了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public Thread() {\n init(null, null, \"Thread-\" + nextThreadNum(), 0);\n}\npublic Thread(Runnable target) {\n init(null, target, \"Thread-\" + nextThreadNum(), 0);\n}\npublic Thread(String name) {\n init(null, null, name, 0);\n}\npublic Thread(ThreadGroup group, String name) {\n init(group, null, name, 0);\n}\npublic Thread(Runnable target, String name) {\n init(null, target, name, 0);\n}\npublic Thread(ThreadGroup group, Runnable target, String name) {\n init(group, target, name, 0);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通过Thread类的源码,我们可以看出,Thread类在进行初始化的时候,都是调用的init()方法,接下来,我们看看init()方法是个啥。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"init()方法","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private void init(ThreadGroup g, Runnable target, String name, long stackSize) {\n init(g, target, name, stackSize, null, true);\n}\nprivate void init(ThreadGroup g, Runnable target, String name,\n long stackSize, AccessControlContext acc,\n boolean inheritThreadLocals) {\n //线程的名称为空,抛出空指针异常\n if (name == null) {\n throw new NullPointerException(\"name cannot be null\");\n }\n\n this.name = name;\n Thread parent = currentThread();\n //获取系统安全管理器\n SecurityManager security = System.getSecurityManager();\n //线程组为空\n if (g == null) {\n //获取的系统安全管理器不为空\n if (security != null) {\n //从系统安全管理器中获取一个线程分组\n g = security.getThreadGroup();\n }\n //线程分组为空,则从父线程获取\n if (g == null) {\n g = parent.getThreadGroup();\n }\n }\n //检查线程组的访问权限\n g.checkAccess();\n //检查权限\n if (security != null) {\n if (isCCLOverridden(getClass())) {\n security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);\n }\n }\n g.addUnstarted();\n //当前线程继承父线程的相关属性\n this.group = g;\n this.daemon = parent.isDaemon();\n this.priority = parent.getPriority();\n if (security == null || isCCLOverridden(parent.getClass()))\n this.contextClassLoader = parent.getContextClassLoader();\n else\n this.contextClassLoader = parent.contextClassLoader;\n this.inheritedAccessControlContext =\n acc != null ? acc : AccessController.getContext();\n this.target = target;\n setPriority(priority);\n if (inheritThreadLocals && parent.inheritableThreadLocals != null)\n this.inheritableThreadLocals =\n ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);\n /* Stash the specified stack size in case the VM cares */\n this.stackSize = stackSize;\n\n //设置线程id\n tid = nextThreadID();\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Thread类中的构造方法是被创建Thread线程的线程调用的,此时,调用Thread的构造方法创建线程的线程就是父线程,在init()方法中,新创建的Thread线程会继承父线程的部分属性。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"run()方法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"既然Thread类实现了Runnable接口,则Thread类就需要实现Runnable接口的run()方法,如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Override\npublic void run() {\n if (target != null) {\n target.run();\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到,Thread类中的run()方法实现非常简单,只是调用了Runnable对象的run()方法。所以,真正的任务是运行在run()方法中的。另外,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"需要注意的是:直接调用Runnable接口的run()方法不会创建新线程来执行任务,如果需要创建新线程执行任务,则需要调用Thread类的start()方法。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"start()方法","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public synchronized void start() {\n //线程不是初始化状态,则直接抛出异常\n if (threadStatus != 0)\n throw new IllegalThreadStateException();\n //添加当前启动的线程到线程组\n group.add(this);\n //标记线程是否已经启动\n boolean started = false;\n try {\n //调用本地方法启动线程\n start0();\n //将线程是否启动标记为true\n started = true;\n } finally {\n try {\n //线程未启动成功\n if (!started) {\n //将线程在线程组里标记为启动失败\n group.threadStartFailed(this);\n }\n } catch (Throwable ignore) {\n /* do nothing. If start0 threw a Throwable then\n it will be passed up the call stack */\n }\n }\n}\n\nprivate native void start0();\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从start()方法的源代码,我们可以看出:","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"start()方法使用synchronized关键字修饰,说明start()方法是同步的,它会在启动线程前检查线程的状态,如果不是初始化状态,则直接抛出异常。所以,一个线程只能启动一次,多次启动是会抛出异常的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这里,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"也是面试的一个坑:面试官:【问题一】能不能多次调用Thread类的start()方法来启动线程吗?【问题二】多次调用Thread线程的start()方法会发生什么?【问题三】为什么会抛出异常?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"调用start()方法后,新创建的线程就会处于就绪状态(如果没有分配到CPU执行),当有空闲的CPU时,这个线程就会被分配CPU来执行,此时线程的状态为运行状态,JVM会调用线程的run()方法执行任务。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"sleep()方法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"sleep()方法可以使当前线程休眠,其代码如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"//本地方法,真正让线程休眠的方法\npublic static native void sleep(long millis) throws InterruptedException;\n\npublic static void sleep(long millis, int nanos)\n throws InterruptedException {\n if (millis < 0) {\n throw new IllegalArgumentException(\"timeout value is negative\");\n }\n\n if (nanos < 0 || nanos > 999999) {\n throw new IllegalArgumentException(\n \"nanosecond timeout value out of range\");\n }\n\n if (nanos >= 500000 || (nanos != 0 && millis == 0)) {\n millis++;\n }\n //调用本地方法\n sleep(millis);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"sleep()方法会让当前线程休眠一定的时间,这个时间通常是毫秒值,这里需要注意的是:","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"调用sleep()方法使线程休眠后,线程不会释放相应的锁。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"join()方法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"join()方法会一直等待线程超时或者终止,代码如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public final synchronized void join(long millis)\n throws InterruptedException {\n long base = System.currentTimeMillis();\n long now = 0;\n\n if (millis < 0) {\n throw new IllegalArgumentException(\"timeout value is negative\");\n }\n\n if (millis == 0) {\n while (isAlive()) {\n wait(0);\n }\n } else {\n while (isAlive()) {\n long delay = millis - now;\n if (delay <= 0) {\n break;\n }\n wait(delay);\n now = System.currentTimeMillis() - base;\n }\n }\n}\n\npublic final synchronized void join(long millis, int nanos)\n throws InterruptedException {\n\n if (millis < 0) {\n throw new IllegalArgumentException(\"timeout value is negative\");\n }\n\n if (nanos < 0 || nanos > 999999) {\n throw new IllegalArgumentException(\n \"nanosecond timeout value out of range\");\n }\n\n if (nanos >= 500000 || (nanos != 0 && millis == 0)) {\n millis++;\n }\n\n join(millis);\n}\n\npublic final void join() throws InterruptedException {\n join(0);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"join()方法的使用场景往往是启动线程执行任务的线程,调用执行线程的join()方法,等待执行线程执行任务,直到超时或者执行线程终止。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"interrupt()方法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"interrupt()方法是中断当前线程的方法,它通过设置线程的中断标志位来中断当前线程。此时,如果为线程设置了中断标志位,可能会抛出InteruptedExeption异常,同时,会清除当前线程的中断状态。这种方式中断线程比较安全,它能使正在执行的任务执行能够继续执行完毕,而不像stop()方法那样强制线程关闭。代码如下所示。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public void interrupt() {\n if (this != Thread.currentThread())\n checkAccess();\n\n synchronized (blockerLock) {\n Interruptible b = blocker;\n if (b != null) {\n interrupt0(); // Just to set the interrupt flag\n b.interrupt(this);\n return;\n }\n }\n //调用本地方法中断线程\n interrupt0();\n}\nprivate native void interrupt0();\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"总结","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作为技术人员,要知其然,更要知其所以然,我那个朋友技术本身不错,各种框架拿来就用,基本没看过常用的框架源码和JDK中常用的API,属于那种CRUD型程序员,这次面试就栽在了一个简单的Thread类上,所以,大家在学会使用的时候,一定要了解下底层的实现才好啊!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"好了,今天就到这儿吧,我是冰河,我们下期见~~","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章