diff --git a/week_04/DelayQueue b/week_04/DelayQueue deleted file mode 100644 index ea9c10d0f7dd99929daafe38fc59c8439490f413..0000000000000000000000000000000000000000 --- a/week_04/DelayQueue +++ /dev/null @@ -1,13 +0,0 @@ -1、总结: - DelayQueue是java并发包下的延时阻塞队列,常用于实现定时任务。 - - 内部存储结构使用优先级队列PriorityQueue q = new PriorityQueue(); - - 入队方法,add(E e)/put(E e) /offer(E e, long timeout, TimeUnit unit)/ ,实现均为offer(E e) - 因为DelayQueue是阻塞队列,且优先级队列是无界的,所以入队不会阻塞不会超时; - - 出队方法,poll()/take() - - demo参考 死磕 java集合之DelayQueue源码分析 - -2、学习参考“彤哥读源码”公众号 diff --git a/week_05/09/Executors.md b/week_05/09/Executors.md new file mode 100644 index 0000000000000000000000000000000000000000..0b74a4c3a2858bca564370fa383a9555d30511b6 --- /dev/null +++ b/week_05/09/Executors.md @@ -0,0 +1,141 @@ +Executors + + +1)预定义线程池 + +```java +//创建固定数量的普通线程池 +public static ExecutorService newFixedThreadPool(int nThreads) { + //通过ThreadPoolExecutor实现类,创建核心线程数及最大线程数都为nThreads的线程池 + //空闲超时时间为0,且由于核心线程数和最大线程数一样,核心线程不会空闲超时后被回收 + //LinkedBlockingQueue为任务队列实现 + return new ThreadPoolExecutor(nThreads, nThreads, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue()); +} + +//nThread为线程池中线程的数量,线程创建的工厂类实现类为threadFactory +public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { + return new ThreadPoolExecutor(nThreads, nThreads, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue(), + threadFactory); +} + +``` + +2)创建可任务窃取的线程池 + +```java +//parallelism并行任务数 +public static ExecutorService newWorkStealingPool(int parallelism) { + + //基于ForkJoinPool创建线程池; + //使用默认线程创建工厂类 + //执行任务异常处理类为null + //任务队列模型为FIFO,true为FIFI,false为FILO + return new ForkJoinPool + (parallelism, + ForkJoinPool.defaultForkJoinWorkerThreadFactory, + null, true); +} + +``` + + +3)创建单个普通线程池 + +```java +//创建单个普通线程池 +public static ExecutorService newSingleThreadExecutor() { + //用FinalizableDelegatedExecutorService进行封装,其会在 + //finalize()方法中调用线程池的shutdown()方法,对线程池进行关闭 + return new FinalizableDelegatedExecutorService + (new ThreadPoolExecutor(1, 1, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue())); +} + +public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { + return new FinalizableDelegatedExecutorService + (new ThreadPoolExecutor(1, 1, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue(), + threadFactory)); +} + +``` + + +4)创建线程数量不限的普通线程池 + +```java +//创建缓存的线程池,即线程池数量不限 +public static ExecutorService newCachedThreadPool() { + return new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue()); +} + + +public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { + return new ThreadPoolExecutor(0, Integer.MAX_VALUE, + 60L, TimeUnit.SECONDS, + new SynchronousQueue(), + threadFactory); +} + +``` + +5)创建单个基于时间调度的线程池 + +```java +//创建单个基于时间调度的线程池 +public static ScheduledExecutorService newSingleThreadScheduledExecutor() { + + //利用DelegatedScheduledExecutorService对线程池进行包装 + //DelegatedScheduledExecutorService利用门面模式包装了ScheduledExecutorService + //使得用户无法修改ScheduledExecutorService中的一些参数 + return new DelegatedScheduledExecutorService + (new ScheduledThreadPoolExecutor(1)); +} + + +``` + + +6)创建多个基于时间调度的线程池 + +```java +//创建多个基于时间调度的线程池 +//创建固定线程池的可基于时间调度的线程池,corePoolSize为核心线程池测数量 +public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { + return new ScheduledThreadPoolExecutor(corePoolSize); +} + + +public static ScheduledExecutorService newScheduledThreadPool( + int corePoolSize, ThreadFactory threadFactory) { + return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); +} +``` + + +7)包装配置不可更改的线程池 + +```java +//对ExecutorService类型线程池进行包装,使用户无法对一些参数进行修改 +public static ExecutorService unconfigurableExecutorService(ExecutorService executor) { + if (executor == null) + throw new NullPointerException(); + return new DelegatedExecutorService(executor); +} + +//对ScheduledExecutorService类型线程池进行包装,使用户无法对一些参数进行修改 +public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) { + if (executor == null) + throw new NullPointerException(); + return new DelegatedScheduledExecutorService(executor); +} + +``` \ No newline at end of file diff --git "a/week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar.md" "b/week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar.md" deleted file mode 100644 index c4db1df2d1220abe8001d6472146e297bd3cbcdb..0000000000000000000000000000000000000000 --- "a/week_05/09/Leetcode-\344\272\244\346\233\277\346\211\223\345\215\260foobar.md" +++ /dev/null @@ -1,72 +0,0 @@ -Leetcode——交替打印foobar - -解法一:利用synchronized - -```java -public class FooBar { - - private int n ; //输出次数 - private boolean isFooBar = true; //是否执行打印 - private Object o = new Object(); //锁对象 - - public FooBar(int n) { - this.n = n; - } - - public void foo(Runnable foo) throws InterruptedException { - for(int i = 0; i < n ; i ++){ - synchronized (o){ - if(!isFooBar){ - o.wait(); - } - foo.run(); - isFooBar = false; - System.out.println("foo"); - o.notify(); - } - - } - } - - public void bar(Runnable bar) throws InterruptedException { - for(int j = 0 ; j < n ;j++){ - synchronized (o){ - if(isFooBar){ - o.wait(); - } - bar.run(); - isFooBar = true; - System.out.println("bar"); - o.notify(); - } - - } - } - public static void main(String[] args) throws InterruptedException { - FooBar fooBar = new FooBar(2); - //创建一个foo线程: - new Thread(){ - public void run(){ - try { - fooBar.foo(new Thread()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }.start(); - //创建一个bar线程 - new Thread(){ - public void run(){ - try { - fooBar.bar(new Thread()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }.start(); - - } -} - -``` - diff --git "a/week_05/09/Leetcode\344\272\244\346\233\277\346\211\223\345\215\2600\344\270\216\345\245\207\345\201\266\346\225\260.md" "b/week_05/09/Leetcode\344\272\244\346\233\277\346\211\223\345\215\2600\344\270\216\345\245\207\345\201\266\346\225\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..6c2a3d44e0960021f4893b2daa7b9ea9076cda6d --- /dev/null +++ "b/week_05/09/Leetcode\344\272\244\346\233\277\346\211\223\345\215\2600\344\270\216\345\245\207\345\201\266\346\225\260.md" @@ -0,0 +1,105 @@ +Leetcode交替打印0与奇偶数 + +题目: + + 每个线程都有一个 printNumber 方法来输出一个整数 + 请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n + +```java + +//利用Semaphore控制实现 +public class ZeroEvenOdd { + + private int n; // n*2n的长度 + + private int num = 0 ; + + Semaphore z = new Semaphore(1); + Semaphore e = new Semaphore(0); + Semaphore o = new Semaphore(0); + + + public ZeroEvenOdd(int n) { + this.n = n; + } + + public void zero() throws InterruptedException { //仅打印出来0 + for(int i=0; i { + + try { + z1.even(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + + }).start(); + + + //线程b 负责打印奇数 + new Thread(() -> { + + try { + z1.odd(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + + }).start(); + + //线程c 负责打印0 + new Thread(() -> { + + try { + z1.zero(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + + }).start(); + + } +} + +``` \ No newline at end of file diff --git a/week_05/09/ThreadLocal.md b/week_05/09/ThreadLocal.md new file mode 100644 index 0000000000000000000000000000000000000000..9e8b1883d55548a6509b0f69db76a2ad058d60ed --- /dev/null +++ b/week_05/09/ThreadLocal.md @@ -0,0 +1,105 @@ +ThreadLocal + +1、 + ThreadLocal 是 Thread的一个局部变量,保存线程的副本 + + ThreadLocalMap 是 ThreadLocal 的内部类,是用基于线性探测法的散列表实现的。 + 每一个线程对象可以往 Map 中添加多个 ThreadLocal 对象为键的键值对,每个键对应的值唯一。所以通过一个 ThreadLocal 对象设置的值,在每个线程中都是唯一且互相独立的。 + 唯一是因为键的唯一性,独立是因为每个线程都有自己的ThreadLocalMap内部变量,它是归线程所有的。 + ThreadLocal是线程Thread中属性threadLocals的管理者,也就是说我们对于ThreadLocal的get, set,remove的操作结果都是针对当前线程Thread实例的threadLocals存,取,删除操作。 + +2、内部类 + + ThreadLocalMap() + + ps:注意其中特殊的类WeakReference + + ```java + static class Entry extends WeakReference> { + /** The value associated with this ThreadLocal. */ + Object value; + + Entry(ThreadLocal k, Object v) { + super(k); + value = v; + } + } + ``` + 简单介绍下很少使用的这个类WeakReference + +| 类型 | 回收时间 | 应用场景| +| :------------------------------ | ---------- | ---------| +|强引用 |一直存活,除非GC Roots不可达|所有程序的场景,基本对象,自定义对象等| +|弱引用 |只能存活到下一次GC前 |生命周期很短的对象,例如ThreadLocal中的Key。| +|软引用 |内存不足时会被回收 |一般用在对内存非常敏感的资源上,用作缓存的场景比较多,例如:网页缓存、图片缓存 +|虚引用 |随时会被回收, 创建了可能很快就会被回收|可能被JVM团队内部用来跟踪JVM的垃圾回收活动| + + +3、构造器 + +```java +//默认构造器 +public ThreadLocal() { +} + +``` + +4、set() :当前线程的 ThreadLocalMap 对象添加键值对,键为 ThreadLocal 对象,值为设置的 value 对象 + +```java +public void set(T value) { + Thread t = Thread.currentThread(); + ThreadLocalMap map = getMap(t); + if (map != null) + map.set(this, value); + else + createMap(t, value); +} + +``` + +5、get(): 线程中调用 get 方法时,如果之前用 set 方法为这个 ThreadLocal 键添加过值,那么就返回设置过的值,否则就返回默认初始值 null + +```java +public T get() { + Thread t = Thread.currentThread(); + ThreadLocalMap map = getMap(t); + if (map != null) { + // 已经调用过set或get方法时,对象值已经设置过,就返回上一次的值 + ThreadLocalMap.Entry e = map.getEntry(this); + if (e != null) { + @SuppressWarnings("unchecked") + T result = (T)e.value; + return result; + } + } + // 没有调用过set或get方法时,对象值没有设置过,就自动设置初始值,并返回初始值 + return setInitialValue(); +} + +private T setInitialValue() { + //获得初始值 + T value = initialValue(); + //set方法 + Thread t = Thread.currentThread(); + ThreadLocalMap map = getMap(t); + if (map != null) + map.set(this, value); + else + createMap(t, value); + return value; +} + + + +``` + +6、模拟复现ThreadLocal导致内存泄漏(内存检察工具没有装好,暂时未提交) + + + +7、学习参考链接: +https://blog.csdn.net/zzg1229059735/article/details/82715741(包含github地址代码) + + + diff --git a/week_05/09/ThreadPoolExecutor.md b/week_05/09/ThreadPoolExecutor.md new file mode 100644 index 0000000000000000000000000000000000000000..4ad53341bd76c84bacde6747bbccb0244604975a --- /dev/null +++ b/week_05/09/ThreadPoolExecutor.md @@ -0,0 +1,265 @@ +ThreadPoolExecutor + +1、认识 + +```java +//继承AbstractExecutorService +public class ThreadPoolExecutor extends AbstractExecutorService{} + +//实现ExecutorService接口 +public abstract class AbstractExecutorService implements ExecutorService{} + +//继承Executor +public interface ExecutorService extends Executor {} + + +public interface Executor { + //启动线程 + void execute(Runnable command); +} + +``` + +2、构造器 + + + +```java + +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + threadFactory, defaultHandler); +} + +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + RejectedExecutionHandler handler) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + Executors.defaultThreadFactory(), handler); +} + + +public ThreadPoolExecutor(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory, + RejectedExecutionHandler handler) { + if (corePoolSize < 0 || + maximumPoolSize <= 0 || + maximumPoolSize < corePoolSize || + keepAliveTime < 0) + throw new IllegalArgumentException(); + if (workQueue == null || threadFactory == null || handler == null) + throw new NullPointerException(); + this.corePoolSize = corePoolSize; + this.maximumPoolSize = maximumPoolSize; + this.workQueue = workQueue; + this.keepAliveTime = unit.toNanos(keepAliveTime); + this.threadFactory = threadFactory; + this.handler = handler; +} + + +``` + +| 序号 | 名称 | 类型 | 含义 | +| :---| --------------| ----------- |----------- | +| 1 | corePoolSize| int |核心线程池大小| +| 2 | maximumPoolSize| int |最大线程池大小| +| 3 | keepAliveTime | long |线程最大空闲时间| +| 4 | unit | TimeUnit|时间单位 | +| 5 | workQueue | BlockingQueue| 线程等待队列| +| 6 | threadFactory | ThreadFactory|线程创建工厂| +| 7 | handler | RejectedExecutionHandler|拒绝策略| + + +3、执行原理execute() + +```java + + public void execute(Runnable command) { + if (command == null) + throw new NullPointerException(); + int c = ctl.get(); + //工作线程 < 核心线程数量 + if (workerCountOf(c) < corePoolSize) { + //创建线程执行任务 + if (addWorker(command, true)) + return; + c = ctl.get(); + } + //运行态,并尝试将任务加入队列 + if (isRunning(c) && workQueue.offer(command)) { + int recheck = ctl.get(); + if (! isRunning(recheck) && remove(command)) + reject(command); + else if (workerCountOf(recheck) == 0) + addWorker(null, false); + } + //使用尝试最大线程运行 + else if (!addWorker(command, false)) + reject(command); //执行拒绝策略 +} + +//接下来看看addWorker(command,boolean)方法, +//先看不同参数值含义: + +addWorker(command, true): 创建核心线程执行任务; +addWorker(command, false):创建非核心线程执行任务; +addWorker(null, false): 创建非核心线程,当前任务为空 + +//继续具体看看该方法的源码分析 + +private boolean addWorker(Runnable firstTask, boolean core) { + // 第一部分:原子操作、自旋、CAS、重读ctl 等结合,直到确定是否可以创建worker, + // 可以则跳出循环继续操作,否则返回false + retry: + for (;;) { + int c = ctl.get(); + int rs = runStateOf(c); + + // Check if queue empty only if necessary. + if (rs >= SHUTDOWN && + ! (rs == SHUTDOWN && + firstTask == null && + ! workQueue.isEmpty())) + return false; + + for (;;) { + int wc = workerCountOf(c); + if (wc >= CAPACITY || + wc >= (core ? corePoolSize : maximumPoolSize)) + return false; + if (compareAndIncrementWorkerCount(c)) + break retry; + c = ctl.get(); // Re-read ctl + if (runStateOf(c) != rs) + continue retry; + // else CAS failed due to workerCount change; retry inner loop + } + } + + // 第二部分:创建worker,这部分使用ReentrantLock锁 + boolean workerStarted = false; //线程启动标志位 + boolean workerAdded = false; //线程是否加入workers 标志位 + Worker w = null; + try { + w = new Worker(firstTask); //创建worker + final Thread t = w.thread; + if (t != null) { + final ReentrantLock mainLock = this.mainLock; + mainLock.lock(); + try { + // Recheck while holding lock. + // Back out on ThreadFactory failure or if + // shut down before lock acquired. + int rs = runStateOf(ctl.get()); + + if (rs < SHUTDOWN || + (rs == SHUTDOWN && firstTask == null)) { + if (t.isAlive()) // precheck that t is startable + throw new IllegalThreadStateException(); + workers.add(w); + int s = workers.size(); + if (s > largestPoolSize) + largestPoolSize = s; + workerAdded = true; + } + } finally { + mainLock.unlock(); + } + if (workerAdded) { + t.start(); //启动线程 + workerStarted = true; + } + } + } finally { + if (! workerStarted) + addWorkerFailed(w); //失败操作 + } + return workerStarted; +} + + +``` + +4、内部类Worker + +```java +//实现了 Runnable 并继承了AbstractQueuedSynchronizer +private final class Worker + extends AbstractQueuedSynchronizer + implements Runnable{ + + /**每个worker有自己的内部线程,ThreadFactory创建失败时是null */ + final Thread thread; + /**初始化任务,可能是null*/ + Runnable firstTask; + /**每个worker的完成任务数*/ + volatile long completedTasks; + + Worker(Runnable firstTask) { + setState(-1); // 禁止线程在启动前被打断 + this.firstTask = firstTask; + this.thread = getThreadFactory().newThread(this); + } + + /*重要的执行方法 */ + public void run() { + runWorker(this); + } + + //state = 0 代表未锁;state = 1 代表已锁 + protected boolean isHeldExclusively() { + return getState() != 0; + } + + protected boolean tryAcquire(int unused) { + if (compareAndSetState(0, 1)) { + setExclusiveOwnerThread(Thread.currentThread()); + return true; + } + return false; + } + + protected boolean tryRelease(int unused) { + setExclusiveOwnerThread(null); + setState(0); + return true; + } + + public void lock() { acquire(1); } + public boolean tryLock() { return tryAcquire(1); } + public void unlock() { release(1); } + public boolean isLocked() { return isHeldExclusively(); } + // interrupt已启动线程 + void interruptIfStarted() { + Thread t; + // 初始化是 state = -1,不会被interrupt + if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { + try { + t.interrupt(); + } catch (SecurityException ignore) { + } + } + } + +} + + +``` + + Worker 实现了简单的 非重入互斥锁,互斥容易理解,非重入是为了避免线程池的一些控制方法获得重入锁,比如setCorePoolSize操作。 + 注意 Worker 实现锁的目的与传统锁的意义不太一样。其主要是为了控制线程是否可interrupt,以及其他的监控,如线程是否 active(正在执行任务)。 + + diff --git a/week_05/09/thread.md b/week_05/09/thread.md new file mode 100644 index 0000000000000000000000000000000000000000..4a195219ee5f99e4a490842c79c1e44e4ec826cf --- /dev/null +++ b/week_05/09/thread.md @@ -0,0 +1,369 @@ +Thread + +1、关于线程 + 看见线程,首先会考虑想到线程与进程的区别,线程的基本状态,线程的调度,线程的切换等相关知识点。(如需要复习,自行查阅相关知识点) + +2、java.lang.Thread类 + + 1)实现Runnable接口 + + 2)属性 + +```java + //线程名字 + private volatile char name[]; + //线程优先级(最大值为10,最小值为1,默认值为5) + private int priority; + private Thread threadQ; + private long eetop; + + /* Whether or not to single_step this thread. */ + private boolean single_step; + + /* 表示线程是否是守护线 */ + private boolean daemon = false; + + /* JVM state */ + private boolean stillborn = false; + + /* 执行任务. */ + private Runnable target; + + /* The group of this thread */ + private ThreadGroup group; + + /* The context ClassLoader for this thread */ + private ClassLoader contextClassLoader; + + /* The inherited AccessControlContext of this thread */ + private AccessControlContext inheritedAccessControlContext; + + /* For autonumbering anonymous threads. */ + private static int threadInitNumber; + + /*栈的深度,默认为0,此数字如何被使用完全取决于虚拟机自己;也有一些虚拟机会忽略此变量值.*/ + private long stackSize; + + /* + * JVM-private state that persists after native thread termination. + */ + private long nativeParkEventPointer; + + /* + * Thread ID + */ + private long tid; + + /* For generating thread ID */ + private static long threadSeqNumber; + + /* + * 为工具提供的线程状态值,初始化值标识当前线程还未运行 + */ + private volatile int threadStatus = 0; + + /** + * The minimum priority that a thread can have. + */ + public final static int MIN_PRIORITY = 1; + + /** + * The default priority that is assigned to a thread. + */ + public final static int NORM_PRIORITY = 5; + + /** + * The maximum priority that a thread can have. + */ + public final static int MAX_PRIORITY = 10; +``` + + 3)构造器 + +```java + //默认构造器 + public Thread() + //传入Runnable接口实现 + public Thread(Runnable target) + //设置当前线程用户组 + public Thread(ThreadGroup group, Runnable target) + //设置传入线程名 + public Thread(String name) + //设置用户组,传入线程名 + public Thread(ThreadGroup group, String name) + //传入Runnable接口实现,传入线程名 + public Thread(Runnable target, String name) + //设置用户组,传入Runnable接口实现,传入线程名 + public Thread(ThreadGroup group, Runnable target, String name) + //设置用户组,传入Runnable接口实现,传入线程名,设置当前线程栈大小 + public Thread(ThreadGroup group, Runnable target, String name,long stackSize) + + + /** + * 初始化线程 + * + * @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 + */ + private void init(ThreadGroup g, Runnable target, String name, + long stackSize, AccessControlContext acc) { + //线程名称不能为空 + if (name == null) { + throw new NullPointerException("name cannot be null"); + } + + Thread parent = currentThread(); + //获得系统的安全管理器 + SecurityManager security = System.getSecurityManager(); + if (g == null) { // 线程的组为空 + + if (security != null) { + // 线程的组为空,从系统安全管理器中获得线 + g = security.getThreadGroup(); + } + + //系统安全管理器为null,则使用当前执行线程的组 + if (g == null) { + g = parent.getThreadGroup(); + } + } + + //检查是否允许当前线程修改线程组的参数 + g.checkAccess(); + + /* + * 是否受限访问 + */ + if (security != null) { + if (isCCLOverridden(getClass())) { + security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); + } + } + + // 将线程组中的容器容量增加1 + g.addUnstarted(); + + this.group = g; + //继承父线程是否为守护线程 + this.daemon = parent.isDaemon(); + //继承父线程的优先级 + this.priority = parent.getPriority(); + this.name = name.toCharArray(); + // 获取类加载器 + 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 (parent.inheritableThreadLocals != null) + this.inheritableThreadLocals = + ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); + /*设置栈的深度 */ + this.stackSize = stackSize; + + /*设置线程id*/ + tid = nextThreadID(); + } +``` +3、常用方法 + +1)start(): + 用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源 + +```java +/** + * 线程启动方法 + * 此方法的调用会引起当前线程的执行;JVM会调用此线程的run()方法, + */ +public synchronized void start() { + + /** + * 0状态值代表new状态 + */ + if (threadStatus != 0) + // 不是新创建的状态抛出异常 + throw new IllegalThreadStateException(); + + /** + * 向线程组里添加此线程,注意:线程创建的时候只是将线程组中的容器容量增加1 + */ + group.add(this); + + boolean started = false; + try { + // 使线程进入可运行状态(runnable) + start0(); + started = true; + } finally { + try { + if (!started) { + // 启动失败,再线程组中删除改线程 + group.threadStartFailed(this); + } + } catch (Throwable ignore) { + /* do nothing. If start0 threw a Throwable then + it will be passed up(放弃) the call stack */ + } + } + } + +``` + +2)run(): + 不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。 + +```java + /** + *线程获得CPU执行权限后执行的方法,实际上是调用的Runnable中的run() + */ + @Override + public void run() { + if (target != null) { + target.run(); + } + } +``` + +3)exit(): + 此方法由系统调用,用于在一个线程退出前做一些扫尾工作。 + +```java + +private void exit() { + if (group != null) { + //加锁执行,删除该线程 + group.threadTerminated(this); + group = null; + } + /* GC回收,全部置为null: see bug 4006245 */ + target = null; + /* 加快释放资源*/ + threadLocals = null; + inheritableThreadLocals = null; + inheritedAccessControlContext = null; + blocker = null; + uncaughtExceptionHandler = null; + } + +``` + +4)interrupt(): + 中断;单独调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常,也就说,它可以用来中断一个正处于阻塞状态的线程;另外,通过interrupt方法和isInterrupted()方法来停止正在运行的线程。 + ( 中断当前线程, 一般来说sleep(),join(),wait()在检查到线程的中断状态的时候,会抛出中断异常InteruptedExeption,以及清除线程的中断状态 ) + +```java + public void interrupt() { + if (this != Thread.currentThread()) + checkAccess(); + // 设置阻塞锁 + synchronized (blockerLock) { + Interruptible b = blocker; + if (b != null) { + interrupt0(); // Just to set the interrupt flag + b.interrupt(this); + return; + } + } + interrupt0(); + } +``` + +5)interrupted() + 中断当前线程是否是中断状态,线程的中断状态会被此方法清除, + 也就是如果此方法两次调用都成功,那么在第二次调用的返回结果为false,除非在第一次调用完后和第二次调用前,当前线程被再次中断, +```java + public static boolean interrupted() { + return currentThread().isInterrupted(true); + } + +``` +6)join() /join(long millis)/join(long millis, int nanos) + +```java + //等待线程死亡 + public final void join() throws InterruptedException { + join(0); + } + + //最多等待参数millis时长,当前线程就会死亡,参数为0时则需要继续等待 + public final synchronized void join(long millis)throws InterruptedException { + long base = System.currentTimeMillis(); + long now = 0; + + if (millis < 0) { //等待时长小于0,不合法,抛出异常 + throw new IllegalArgumentException("timeout value is negative"); + } + + if (millis == 0) { //等待时长为0,继续等 + while (isAlive()) { + wait(0); + } + } else { + while (isAlive()) { + long delay = millis - now; + if (delay <= 0) { + break; + } + wait(delay); + now = System.currentTimeMillis() - base; + } + } + } + + //最多等待参数millis毫秒加nanos纳秒时长,当前线程就会死亡,参数为0时则需要继续等待 + public final synchronized void join(long millis, int nanos)throws InterruptedException { + if (millis < 0) { + throw new IllegalArgumentException("timeout value is negative"); + } + + if (nanos < 0 || nanos > 999999) { + throw new IllegalArgumentException( + "nanosecond timeout value out of range"); + } + + if (nanos >= 500000 || (nanos != 0 && millis == 0)) { + millis++; + } + + join(millis); + } + +``` + +7) dumpStack() + +```java + //将当前线程的堆栈跟踪打印到标准错误流,此方法只用于debug + public static void dumpStack() { + new Exception("Stack trace").printStackTrace(); + } + +``` + +4、总结 + +5、阅读参考链接: + + https://blog.csdn.net/lxx19941220/article/details/92587043 + https://www.cnblogs.com/albertrui/p/8391447.html + + + + + + + + + + + +