自定义线程池:
AtomicLong atomicLong = new AtomicLong();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,
3,
1000,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(1024),
r -> {
Thread t = new Thread(r);
t.setName("yc"+atomicLong.decrementAndGet());
if (t.isDaemon()) {
t.setDaemon(false);
}
if (Thread.NORM_PRIORITY != t.getPriority()) {
t.setPriority(Thread.NORM_PRIORITY);
}
return t;
});
线程池有两种提交方式,execute , submit ,两者的不同点有:
1、打印异常信息
execute 会直接把异常信息打印在控制台
submit 不会打印异常信息,可以通过Future.get()来获取异常信息
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println("---2--"+Thread.currentThread().getName());
throw new RuntimeException("execute我报错了");
}
});
threadPoolExecutor.submit(new Runnable() {
@Override
public void run() {
System.out.println("---1--"+Thread.currentThread().getName());
throw new RuntimeException("submit我报错了");
}
});
submit 用get来获取异常信息:
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println("---2--"+Thread.currentThread().getName());
throw new RuntimeException("execute我报错了");
}
});
Future f = threadPoolExecutor.submit(new Runnable() {
@Override
public void run() {
System.out.println("---1--"+Thread.currentThread().getName());
throw new RuntimeException("submit我报错了");
}
});
f.get();
2、是否会删除当前线程,重新新建线程
execute 会删除当前线程,重新新建线程
submit 线程不会发生变化
execute提交的时候 task.run();出现异常会catch异常,跳出while循环,执行processWorkerExit方法
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
在processWorkerExit方法中会把当前线程移除,因为当前线程已经跳出循环了,已经执行完了,此线程就自动销毁了,需要在workers中移除,再新建一个线程
private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
workers.remove(w);
} finally {
mainLock.unlock();
}
tryTerminate();
int c = ctl.get();
if (runStateLessThan(c, STOP)) {
if (!completedAbruptly) {
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if (min == 0 && ! workQueue.isEmpty())
min = 1;
if (workerCountOf(c) >= min)
return; // replacement not needed
}
addWorker(null, false);
}
}
但是 submit 执行 task.run(); 时候就算执行出现异常了,在runWorker方法里面也不会catch到,
这是因为此时的task,是furtureTask其会执行以下的run()方法
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
在这个run方法中,已经对异常进行catch了,所以就不会在runWorker方法中进行catch,因此不会执行processWorkerExit方法,改线程还是在进行while循环 getTask()
/**
* Performs blocking or timed wait for a task, depending on
* current configuration settings, or returns null if this worker
* must exit because of any of:
* 1. There are more than maximumPoolSize workers (due to
* a call to setMaximumPoolSize).
* 2. The pool is stopped.
* 3. The pool is shutdown and the queue is empty.
* 4. This worker timed out waiting for a task, and timed-out
* workers are subject to termination (that is,
* {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
* both before and after the timed wait, and if the queue is
* non-empty, this worker is not the last thread in the pool.
*
* @return task, or null if the worker must exit, in which case
* workerCount is decremented
*/
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
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;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
getTask就是从队列里面去拿取任务,如果是堵塞队列的话,则take的时候,没有任务会一只堵塞
注意:当线程池里面当一个线程出现异常后,不会影响其他线程的运行