亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java之Thread不捕獲異常默認處理邏輯

 更新時間:2023年12月11日 15:31:12   作者:QMCoder  
這篇文章主要介紹了java之Thread不捕獲異常默認處理邏輯,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

直接new Thread(()->{})默認處理邏輯

Thread 類, 發(fā)生異常未捕獲,默認JVM調(diào)用 dispatchUncaughtException 方法

	
    /**
     * Dispatch an uncaught exception to the handler. This method is
     * intended to be called only by the JVM.
     */
    private void dispatchUncaughtException(Throwable e) {
        getUncaughtExceptionHandler().uncaughtException(this, e);
    }

	// 線程實例的默認異常處理, 需要手動設(shè)置, 不設(shè)置默認為null
    private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
    /**
     * Returns the handler invoked when this thread abruptly terminates
     * due to an uncaught exception. If this thread has not had an
     * uncaught exception handler explicitly set then this thread's
     * <tt>ThreadGroup</tt> object is returned, unless this thread
     * has terminated, in which case <tt>null</tt> is returned.
     * @since 1.5
     * @return the uncaught exception handler for this thread
     */
    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
        return uncaughtExceptionHandler != null ?
            uncaughtExceptionHandler : group;  // group就是線程對應(yīng)的線程組
    }

什么都不設(shè)置, 默認最后回來到ThreadGroup的uncaughtException 方法

    
    /**
     * Called by the Java Virtual Machine when a thread in this
     * thread group stops because of an uncaught exception, and the thread
     * does not have a specific {@link Thread.UncaughtExceptionHandler}
     * installed.
     * <p>
     * The <code>uncaughtException</code> method of
     * <code>ThreadGroup</code> does the following:
     * <ul>
     * <li>If this thread group has a parent thread group, the
     *     <code>uncaughtException</code> method of that parent is called
     *     with the same two arguments.
     * <li>Otherwise, this method checks to see if there is a
     *     {@linkplain Thread#getDefaultUncaughtExceptionHandler default
     *     uncaught exception handler} installed, and if so, its
     *     <code>uncaughtException</code> method is called with the same
     *     two arguments.
     * <li>Otherwise, this method determines if the <code>Throwable</code>
     *     argument is an instance of {@link ThreadDeath}. If so, nothing
     *     special is done. Otherwise, a message containing the
     *     thread's name, as returned from the thread's {@link
     *     Thread#getName getName} method, and a stack backtrace,
     *     using the <code>Throwable</code>'s {@link
     *     Throwable#printStackTrace printStackTrace} method, is
     *     printed to the {@linkplain System#err standard error stream}.
     * </ul>
     * <p>
     * Applications can override this method in subclasses of
     * <code>ThreadGroup</code> to provide alternative handling of
     * uncaught exceptions.
     *
     * @param   t   the thread that is about to exit.
     * @param   e   the uncaught exception.
     * @since   JDK1.0
     */
    public void uncaughtException(Thread t, Throwable e) {
        if (parent != null) {
            parent.uncaughtException(t, e);
        } else {
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();  // 全局的異常處理器 Thread靜態(tài)字段, 手動設(shè)置, 不設(shè)置默認為null
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" ");
                e.printStackTrace(System.err);  // 都不設(shè)置默認輸出到 標(biāo)準錯誤輸出
            }
        }
    }

線程池默認處理邏輯

ThreadPoolExecutor#runWorker 方法

    
    /**
     * Main worker run loop.  Repeatedly gets tasks from queue and
     * executes them, while coping with a number of issues:
     *
     * 1. We may start out with an initial task, in which case we
     * don't need to get the first one. Otherwise, as long as pool is
     * running, we get tasks from getTask. If it returns null then the
     * worker exits due to changed pool state or configuration
     * parameters.  Other exits result from exception throws in
     * external code, in which case completedAbruptly holds, which
     * usually leads processWorkerExit to replace this thread.
     *
     * 2. Before running any task, the lock is acquired to prevent
     * other pool interrupts while the task is executing, and then we
     * ensure that unless pool is stopping, this thread does not have
     * its interrupt set.
     *
     * 3. Each task run is preceded by a call to beforeExecute, which
     * might throw an exception, in which case we cause thread to die
     * (breaking loop with completedAbruptly true) without processing
     * the task.
     *
     * 4. Assuming beforeExecute completes normally, we run the task,
     * gathering any of its thrown exceptions to send to afterExecute.
     * We separately handle RuntimeException, Error (both of which the
     * specs guarantee that we trap) and arbitrary Throwables.
     * Because we cannot rethrow Throwables within Runnable.run, we
     * wrap them within Errors on the way out (to the thread's
     * UncaughtExceptionHandler).  Any thrown exception also
     * conservatively causes thread to die.
     *
     * 5. After task.run completes, we call afterExecute, which may
     * also throw an exception, which will also cause thread to
     * die. According to JLS Sec 14.20, this exception is the one that
     * will be in effect even if task.run throws.
     *
     * The net effect of the exception mechanics is that afterExecute
     * and the thread's UncaughtExceptionHandler have as accurate
     * information as we can provide about any problems encountered by
     * user code.
     *
     * @param w the worker
     */
    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;    // 發(fā)生異常直接拋出, 最后也會走到Thread的異常處理邏輯
                    } catch (Error x) {
                        thrown = x; throw x;  // 發(fā)生異常直接拋出 最后也會走到Thread的異常處理邏輯
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x); // 發(fā)生異常拋出 最后也會走到Thread的異常處理邏輯
                    } finally {
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);  // 發(fā)生異常whiie循環(huán)結(jié)束  當(dāng)前線程退出處理  
        }
    }

線程池的 execute 和 submit 方法異常處理 異同

    /**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);  // 任務(wù)被包裝成FutureTask, FutureTask的run方法處理了異常, 所以如果默認task不處理異常,需要調(diào)用futureTask.get()方法獲取結(jié)果或者異常,否則表象就是異常吞掉了
        execute(ftask);
        return ftask;
    }
    /**
     * Returns a {@code RunnableFuture} for the given callable task.
     *
     * @param callable the callable task being wrapped
     * @param <T> the type of the callable's result
     * @return a {@code RunnableFuture} which, when run, will call the
     * underlying callable and which, as a {@code Future}, will yield
     * the callable's result as its result and provide for
     * cancellation of the underlying task
     * @since 1.6
     */
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

    /**
     * Executes the given task sometime in the future.  The task
     * may execute in a new thread or in an existing pooled thread.
     *
     * If the task cannot be submitted for execution, either because this
     * executor has been shutdown or because its capacity has been reached,
     * the task is handled by the current {@code RejectedExecutionHandler}.
     *
     * @param command the task to execute
     * @throws RejectedExecutionException at discretion of
     *         {@code RejectedExecutionHandler}, if the task
     *         cannot be accepted for execution
     * @throws NullPointerException if {@code command} is null
     */
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
        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);
    }    

FutureTask 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);  // 異常被賦值到成員變量, 通過get方法獲取結(jié)果或者異常
                }
                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);
        }
    }



    /**
     * Causes this future to report an {@link ExecutionException}
     * with the given throwable as its cause, unless this future has
     * already been set or has been cancelled.
     *
     * <p>This method is invoked internally by the {@link #run} method
     * upon failure of the computation.
     *
     * @param t the cause of failure
     */
    protected void setException(Throwable t) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = t;
            UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
            finishCompletion();
        }
    }

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Mybatis?一級緩存和二級緩存原理區(qū)別

    Mybatis?一級緩存和二級緩存原理區(qū)別

    這篇文章主要介紹了Mybatis?一級緩存和二級緩存原理區(qū)別?,文章通過圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • 分析Springboot中嵌套事務(wù)失效原因詳解

    分析Springboot中嵌套事務(wù)失效原因詳解

    這篇文章主要為大家介紹了分析Springboot中嵌套事務(wù)失效原因詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-11-11
  • IDEA項目如何取消git版本管控并添加svn版本控制

    IDEA項目如何取消git版本管控并添加svn版本控制

    在公司內(nèi)部服務(wù)器環(huán)境下,將代碼倉庫從Gitee的Git遷移到SVN可以避免外部版本控制的風(fēng)險,遷移過程中,先刪除項目的.git文件夾,再通過Eclipse的設(shè)置界面刪除原Git配置并添加SVN配置,之后,將項目提交到SVN倉庫,確保使用ignore列表過濾不必要的文件
    2024-10-10
  • 快速解決VS Code報錯:Java 11 or more recent is required to run. Please download and install a recent JDK

    快速解決VS Code報錯:Java 11 or more recent is required to run. Ple

    這篇文章主要介紹了快速解決VS Code報錯:Java 11 or more recent is required to run. Please download and install a recent JDK的相關(guān)資料,需要的朋友可以參考下
    2020-09-09
  • Mybatis執(zhí)行流程、緩存原理及相關(guān)面試題匯總

    Mybatis執(zhí)行流程、緩存原理及相關(guān)面試題匯總

    最近剛學(xué)完MyBatis,趁著大好機會,總結(jié)一下它的執(zhí)行流程,面試也愛問這個,下面這篇文章主要給大家介紹了關(guān)于Mybatis執(zhí)行流程、緩存原理及相關(guān)面試題的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • 詳解使用JavaCV/OpenCV抓取并存儲攝像頭圖像

    詳解使用JavaCV/OpenCV抓取并存儲攝像頭圖像

    本篇文章主要介紹了使用JavaCV/OpenCV抓取并存儲攝像頭圖像,實例分析了使用JavaCV/OpenCV抓取并存儲攝像頭圖像的技巧,非常具有實用價值,需要的朋友可以參考下
    2017-04-04
  • SpringBoot實現(xiàn)對超大文件進行異步壓縮下載的使用示例

    SpringBoot實現(xiàn)對超大文件進行異步壓縮下載的使用示例

    在Web應(yīng)用中,文件下載功能是一個常見的需求,本文介紹了SpringBoot實現(xiàn)對超大文件進行異步壓縮下載的使用示例,具有一定的參考價值,感興趣的可以了解一下,
    2023-09-09
  • 詳解Spring MVC4 純注解配置教程

    詳解Spring MVC4 純注解配置教程

    本篇文章主要介紹了Spring MVC4 純注解配置教程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • Java中的HashMap源碼解析

    Java中的HashMap源碼解析

    這篇文章主要介紹了Java中的HashMap源碼解析,當(dāng)HashMap中的其中一個鏈表的對象個數(shù)如果達到了8個,此時如果數(shù)組長度沒有達到64,那么HashMap會先擴容解決,如果已經(jīng)達到了64,那么這個鏈表會變成紅黑樹,需要的朋友可以參考下
    2023-12-12
  • Java Annotation注解相關(guān)原理代碼總結(jié)

    Java Annotation注解相關(guān)原理代碼總結(jié)

    這篇文章主要介紹了Java Annotation注解相關(guān)原理代碼總結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07

最新評論