来源:https://www.cnblogs.com/guozp/p/10344446.htmlhtml
咱们在建立线程池的时候,必定要给线程池名字,以下这种写法,线程是默认直接生成的:java
public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int finalI = i; executorService.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + ":" + finalI); } }); } }
最后的输出:less
pool-1-thread-3:2 pool-1-thread-2:1 pool-1-thread-3:4 pool-1-thread-1:3 pool-1-thread-3:6 pool-1-thread-2:5 pool-1-thread-3:8 pool-1-thread-1:7 pool-1-thread-2:9
Executors中有默认的线程工厂的实现:ide
static class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }
咱们能够改造一下this
public class NamedThreadFactory implements ThreadFactory { private final AtomicInteger threadNumber; private final String name; private final boolean isDaemon; public NamedThreadFactory(String name) { this(name, false); } public NamedThreadFactory(String name, boolean daemon) { this.threadNumber = new AtomicInteger(1); this.isDaemon = daemon; this.name = name + "-thread-pool-"; } public Thread newThread(Runnable r) { Thread t = new Thread(r, this.name + this.threadNumber.getAndIncrement()); t.setDaemon(this.isDaemon); if (t.getPriority() != Thread.NORM_PRIORITY){ t.setPriority(Thread.NORM_PRIORITY); } return t; } }
那咱们看下改造以后的输出结果:spa
有名字的线程池-thread-pool-1:0 有名字的线程池-thread-pool-3:2 有名字的线程池-thread-pool-1:3 有名字的线程池-thread-pool-2:1 有名字的线程池-thread-pool-1:5 有名字的线程池-thread-pool-1:7 有名字的线程池-thread-pool-1:8 有名字的线程池-thread-pool-3:4 有名字的线程池-thread-pool-1:9 有名字的线程池-thread-pool-2:6
这样的话,当咱们应用线上出现问题,须要经过jstack查看线程堆栈的时候,就能够知道是哪些线程出现的问题,不然看到的都是统一的命名方式,看到都是清一色的线程,增长排查问题的难度线程
Java中线程执行的任务接口java.lang.Runnable 要求不抛出Checked异常,code
public interface Runnable { public abstract void run(); }
那么若是 run() 方法中抛出了RuntimeException,将会怎么处理了?htm
线程出现未捕获异常后,JVM将调用Thread中的dispatchUncaughtException方法把异常传递给线程的未捕获异常处理器对象
private void dispatchUncaughtException(Throwable e) { getUncaughtExceptionHandler().uncaughtException(this, e); } public UncaughtExceptionHandler getUncaughtExceptionHandler() { return uncaughtExceptionHandler != null ? uncaughtExceptionHandler : group; }
Thread中存在两个UncaughtExceptionHandler。一个是静态的defaultUncaughtExceptionHandler,另外一个是非静态uncaughtExceptionHandler。
// null unless explicitly set private volatile UncaughtExceptionHandler uncaughtExceptionHandler; // null unless explicitly set private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
若是没有设置uncaughtExceptionHandler,将使用线程所在的线程组来处理这个未捕获异常。线程组ThreadGroup实现了UncaughtExceptionHandler,因此能够用来处理未捕获异常。ThreadGroup类定义:
private ThreadGroup group; class ThreadGroup implements Thread.UncaughtExceptionHandler{}
ThreadGroup实现的uncaughtException以下:
public void uncaughtException(Thread t, Throwable e) { if (parent != null) { parent.uncaughtException(t, e); } else { Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh != null) { ueh.uncaughtException(t, e); } else if (!(e instanceof ThreadDeath)) { System.err.print("Exception in thread \"" + t.getName() + "\" "); e.printStackTrace(System.err); } } }
默认状况下,线程组处理未捕获异常的逻辑是,首先将异常消息通知给父线程组,而后尝试利用一个默认的defaultUncaughtExceptionHandler来处理异常,若是没有默认的异常处理器则将错误信息输出到System.err。也就是JVM提供给咱们设置每一个线程的具体的未捕获异常处理器,也提供了设置默认异常处理器的方法,一般java.lang.Thread对象运行设置一个默认的异常处理方法:
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission( new RuntimePermission("setDefaultUncaughtExceptionHandler") ); } defaultUncaughtExceptionHandler = eh; }
而这个默认的静态全局的异常捕获方法是直接输出异常堆栈。
固然,咱们能够覆盖此默认实现,只须要实现java.lang.Thread.UncaughtExceptionHandler接口便可
public interface UncaughtExceptionHandler { void uncaughtException(Thread t, Throwable e); }
public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; } protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { return new FutureTask<T>(runnable, value); } public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable } public static <T> Callable<T> callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter<T>(task, result); } //最终FutureTask中的callable指向的是一个RunnableAdapter,而RunnableAdapter的call方法也是调用了咱们传进来的task的run方法,返回的是null static final class RunnableAdapter<T> implements Callable<T> { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { task.run(); return result; } }
protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); //执行的Callable,对应的t必定是Null if (t == null && r instanceof Future) { try { Future future = (Future) r; if (future.isDone()){ // 判断任务是否执行完成 future.get(); } } catch (CancellationException ce) { t = ce; } catch (ExecutionException ee) { t = ee.getCause(); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } }
public void execute3(){ List<Integer> data = new ArrayList<Integer>(100); for (int i = 0; i < 100; i++) { data.add(i + 10); } List<List<Integer>> partition = Lists.partition(data, 20); final CountDownLatch countDownLatch = new CountDownLatch(partition.size()); for (final List<Integer> dataToHandle : partition) { threadPoolExecutor.execute(new Runnable() { @Override public void run() { try{ for (Integer i : dataToHandle) { doSomeThing(i); } }catch (Exception e){ logger.error(e.getMessage(), e); }finally { countDownLatch.countDown(); } } }); } try { countDownLatch.await(); } catch (InterruptedException e) { logger.error(e.getMessage(), e); } logger.info("任务执行结束..."); }
public void execute3(){ List<Integer> data = new ArrayList<Integer>(100); for (int i = 0; i < 100; i++) { data.add(i + 10); } final List<List<Integer>> partition = Lists.partition(data, 20); final CountDownLatch countDownLatch = new CountDownLatch(partition.size()); new Thread(new Runnable() { @Override public void run() { for (final List<Integer> dataToHandle : partition) { try { threadPoolExecutor.execute(new Runnable() { @Override public void run() { try{ for (Integer i : dataToHandle) { doSomeThing(i); } }catch (Exception e){ logger.error(e.getMessage(), e); }finally { countDownLatch.countDown(); } } }); } catch (RejectedExecutionException e) { logger.error(e.getMessage(), e); //处理完异常以后须要补充countDownLatch事件 countDownLatch.countDown(); } } } }).start(); try { countDownLatch.await(); } catch (InterruptedException e) { logger.error(e.getMessage(), e); } logger.info("任务执行结束..."); }
来源:https://www.cnblogs.com/guozp/p/10344446.html