union all和union的区别
union all
:包含重复行
union
:不包含重复行
线程池的shutdown()与shutdownNow()方法的区别
shutdown(),调用shutdown方法,线程池会拒绝接收新的任务,处理中的任务和阻塞队列中的任务会继续处理。
public class ThreadPoolTest {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 2,
1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2));
Runnable runnable = () -> {
System.out.println(Thread.currentThread().getName() + "before ~~~");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "after ~~~");
};
pool.execute(new Thread(runnable));
pool.execute(new Thread(runnable));
pool.execute(new Thread(runnable));
pool.shutdown();
System.out.println("活跃线程数:" + pool.getActiveCount() + ",队列任务数:" + pool.getQueue().size());
// pool.execute(new Thread(runnable));
}
}
shutdownNow()
,会给workers中所有的线程发送interrupt
信号,将延迟队列的任务移除并返回。
原理分析
执行任务,尝试添加线程。
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);
}
ThreadPoolExecutor#addWorker
,当判断当前线程池的状态已经是SHUTDOWN
,返回false,执行拒绝策略。
private boolean addWorker(Runnable firstTask, boolean core) {
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
}
}
// ...
}
ThreadPoolExecutor#shutdown
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
ThreadPoolExecutor#advanceRunState
,修改状态为SHUTDOWN
private void advanceRunState(int targetState) {
for (;;) {
int c = ctl.get();
if (runStateAtLeast(c, targetState) ||
ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
break;
}
}
ThreadPoolExecutor#interruptIdleWorkers()
,对于空闲线程,执行interrupt
方法。
private void interruptIdleWorkers() {
interruptIdleWorkers(false);
}
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
ThreadPoolExecutor#shutdownNow
,修改任务状态为STOP
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
ThreadPoolExecutor#interruptWorkers
,发送中断信号。
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
}
ThreadPoolExecutor#drainQueue
,将延迟队列中的任务数据移动到任务list中。
private List<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
ArrayList<Runnable> taskList = new ArrayList<Runnable>();
q.drainTo(taskList);
if (!q.isEmpty()) {
for (Runnable r : q.toArray(new Runnable[0])) {
if (q.remove(r))
taskList.add(r);
}
}
return taskList;
}
spring中 initMethod,@PostConstruct,InitializingBean 初始化的顺序
https://juejin.cn/post/7006965516891848741
@PostConstruct > InitializingBean > initMethod
PostConstruct
是实例初始化的时候调用的。
-
实例初始化会调用
aware
方法,BeanNameAware
,BeanClassLoaderAware
和BeanFactoryAware
。 -
调用
BeanPostProcessor
的前置方法 -
执行
InitializingBean
的afterPropertiesSet
方法。如果有init
方法,执行init
方法。 -
调用
BeanPostProcessor
的后置方法
@PostConstruct
的具体执行的后置处理器是InitDestroyAnnotationBeanPostProcessor
InitializingBean
的执行处理在后置处理器的前置方法执行完后。
initMethod
初始化方法在InitializingBean
后执行的
Spring 配置中的 classpath:
与 classpath*:
的区别
classpath:
,加载一个指定location的资源文件。
classpath*:
,会加载所有指定location的资源文件。
守护线程是什么?守护线程和非守护线程的区别是?守护线程的作用是?
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
System.out.println(System.currentTimeMillis());
}
});
// t1.setDaemon(true);
t1.start();
Thread.sleep(2000);
}
用户线程就是非守护线程,默认创建的线程就是用户线程。当主线线程停止,用户线程也会停下来。如果是用户线程,则会一直运行。
Java里一个线程调用了Thread.interrupt()到底意味着什么?
- 如果当前线程处在阻塞状态(例如sleep,join,wait),会退出阻塞状态,抛出
InterruptedException
异常。 - 如果正常活动,修改中断标志位为true
public class InterruptTest {
public static void main(String[] args) throws InterruptedException {
// t1();
t2();
}
private static void t2() throws InterruptedException {
Thread thread = new Thread(() -> {
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
TimeUnit.MILLISECONDS.sleep(10);
thread.interrupt();
}
private static void t1() throws InterruptedException {
Thread thread = new Thread(() -> {
System.out.println("开始搬砖!");
//只要代码里没有异常,那么我们可以通过判断线程是否中断来执行业务操作
//当其他线程发出线程中断信号后就会跳出正在执行的任务,往下执行使线程结束运行。
while (!Thread.currentThread().isInterrupted()) {
System.out.println("西西弗斯的陷阱:无脑循环,日复一日搬砖!");
}
System.out.println("神迹出现,结束搬砖!");
System.out.println(Thread.currentThread().isInterrupted());//true
System.out.println(Thread.currentThread().isInterrupted());//true
System.out.println(Thread.interrupted());//true
System.out.println(Thread.interrupted());//true
});
thread.start();
TimeUnit.MILLISECONDS.sleep(10);
System.out.println("启动超级进化形态!");
thread.interrupt();
}
}
Thread的静态函数interrupted与Thread的对象函数isInterrupted比较
-
静态方法
Thread.interrupted()
会在检测线程中断状态标志是否为true后,还会将中断状态标志重置为false。 -
对象方法
thread.isInterrupted()
只是检测线程中断状态标志。
sleep和wait有什么区别?
wait
方法必须在synchronized
方法块中,sleep
可以单独使用。- wait方法是
Object
中的,sleep方法是Thread
中的。 - 唤醒方式不同。sleep自动唤醒,wait是需要别的线程notify唤醒的。
- sleep在休眠时不释放锁,wait在休眠时会释放锁。
- 调用sleep方法会进入到
TIMED_WAITING
,而调用wait方法会进入到WAITING
。
线程的五种状态
- 新建。
new Thread()
- 运行。执行
start
方法之后 - 无限等待。
Object.wait()
- 有限等待。
Object.wait(timeout)
或者Thread.sleep(timeout)
- 阻塞。阻塞是在等待排他锁,
synchronized
- 结束,
terminated
。
Thread.join()
方法
Thread.join()
会造成主线程阻塞。当线程执行结束之后,会唤醒主线程。
public class ThreadJoinTest {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
// while (true){
System.out.println("t1 run");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// }
});
Thread t2 = new Thread(() -> {
System.out.println("t2 run");
});
Thread t3 = new Thread(() -> {
System.out.println("t3 run");
});
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
}
}