线程的状态
线程池
线程池参数 老八股文了。俩个时间参数是 线程空闲回收时间,回收时候用的。
execute 提交时候的流程 老八股文了。
线程回收条件
while (task != null || (task = getTask()) != null) {
//task 为null 会去 拿线程执行,拿不到就回收。
}
拿不到的条件。
1、队列空。线程池停了等情况
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
2、 (工作线程大于最小线程 || 超过空闲时间)&&(工作线程大于1 || 队列空)
工作线程大于1 是应为自己停了怎么也得有个在运行的,队列空就不需要了
int wc = workerCountOf(c);
// Are workers subject to culling?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
笔试题
ab俩个线程交替打印,
可以取个巧直接用synchronized wait notifyAll
Object o = new Object();
AtomicInteger count = new AtomicInteger(0);
new Thread(new P("a", o, count),"aaa").start();
new Thread(new P("b", o, count),"bbb").start();
static class P implements Runnable{
String info;
final Object lock;
AtomicInteger count;
public P(String info, Object lock, AtomicInteger count) {
//省略
}
@SneakyThrows
@Override
public void run() {
synchronized (lock){
while (this.count.get() < 20){
log.info(info + "" +count.incrementAndGet());
lock.notifyAll();
// lock.wait();
lock.wait(1000*20);
log.info("100毫秒");
}
}
}
}
三个线程交替打印
用ReentrantLock的Condition
public static void main(String[] args){
AtomicInteger count = new AtomicInteger(0);
ReentrantLock lock = new ReentrantLock();
// 声明互相等待的条件
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
new Thread(new P2(lock,condition1,condition2,"a", count),"aaa").start();
new Thread(new P2(lock,condition2,condition3,"b", count),"bbb").start();
new Thread(new P2(lock,condition3,condition1,"c", count),"ccc").start();
lock.lock();
condition1.signal();
lock.unlock();
}
static class P2 implements Runnable{
public P2(ReentrantLock lock,Condition condition, Condition conditionNext, String info, AtomicInteger count) {
this.lock = lock;
this.condition = condition;
this.conditionNext = conditionNext;
this.info = info;
this.count = count;
}
ReentrantLock lock;
Condition condition;
Condition conditionNext;
String info;
AtomicInteger count;
@SneakyThrows
@Override
public void run() {
while (this.count.get() < 20) {
lock.lock();
condition.await();
log.info(info + "" + count.incrementAndGet());
conditionNext.signal();
lock.unlock();
}
}
}
AQS (AbstractQueuedSynchronizer)
参考Java并发之AQS详解
抽象的队列式的同步器,AQS定义了一套多线程访问共享资源的同步器框架,子类只需维护volatile int status(共享资源数量) 就可以。至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。
主要实现四个方法 都是返回boolean类型的。
- isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
- tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
- tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
- tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
- tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。
内部类Node
双向列表的Node。节点核心参数 waitStatus 、thread。
addWaiter的时候会创建Node。addWaiter就是追加一个Node到队列尾。
Node的 五种状态 (waitStatus的四个值)
- CANCELLED(1):表示当前结点已取消调度。当timeout或被中断(响应中断的情况下),会触发变更为此状态,进入该状态后的结点将不会再变化
- SIGNAL(-1):表示后继结点在等待当前结点唤醒。后继结点入队时,会将前继结点的状态更新为SIGNAL
- CONDITION(-2):表示结点等待在Condition上,当其他线程调用了Condition的signal()方法后,CONDITION状态的结点将从等待队列转移到同步队列中,等待获取同步锁
- PROPAGATE(-3):共享模式下,前继结点不仅会唤醒其后继结点,同时也可能会唤醒后继的后继结点
- 0:新结点入队时的默认状态
负值表示结点处于有效等待状态,而正值表示结点已被取消。所以源码中很多地方用>0、<0来判断结点的状态是否正常。
获取成功就直接返回,获取失败就排队去。
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
释放成功就看要不要,通知后续节点,释放失败就返回释放失败。
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/76452.html