为什么要夯实基本功?
夯实编程基本功对于成为一名优秀的Java技术专家至关重要。它不仅帮助你建立坚实的基础,提高编程效率和问题解决能力,还为你学习和掌握更高级的技术打下了基础。因此,无论是初学者还是有经验的开发者,都应该注重夯实编程基本功。
-
建立坚实的基础:夯实编程基本功可以帮助你建立坚实的编程基础,掌握核心概念和语法规则。这为你在后续的学习和实践中提供了稳定的基础,使你能够更好地理解和应用更高级的概念和技术。
-
提高编程效率:掌握编程基本功可以提高你的编程效率。当你熟悉基本的语法和常用的编程技巧时,你能够更快地编写代码,减少错误和调试的时间,提高开发效率。
-
增强问题解决能力:夯实编程基本功可以培养你的问题解决能力。当你熟悉基本的编程概念和技巧时,你能够更好地分析和解决编程问题,找到合适的解决方案。
-
为学习高级技术打下基础:夯实编程基本功是学习和掌握更高级技术的基础。当你掌握了基本的编程概念和技巧后,你能够更轻松地理解和学习更高级的概念和技术,如面向对象编程、设计模式、并发编程等。
线程Thread
java.lang.Thread类
java
Thread(Runnable target)
这个构造函数用于创建一个新的线程,其主要任务是执行提供的Runnable对象的run()方法。
java
void start()
此方法用于启动线程,进而触发run()方法的执行。调用此方法后,会立即返回,此时新创建的线程将开始并行运行。
java
void run()
这个方法被设计来调用与其关联的Runnable对象的run方法,以实现线程的具体任务。
java.lang.Runnable类
java
void run()
必须重写这个方法,并在其中详细定义需要执行的具体任务指令。
线程状态
线程可以有如下6种状态,若要了解线程的当前状态,可通过调用getState
方法来获取。线程可能会因为两种原因而终止:一种是因为run
方法执行完毕而自然结束;另一种是因为run
方法中抛出了一个未捕获的异常,导致线程意外终止。
中断线程
当线程的run
方法执行到方法体中的最后一条语句,并通过执行return
语句完成返回,或者在方法内部发生了未被捕获的异常时,该线程将会结束其执行。存在一种能够强制结束线程的方式,但更为推荐的做法是使用interrupt方法来请求线程终止。这种方式更为安全和可控。
Thread的中断方法
java
void interrupt()
向线程发出中断请求后,其中断状态将被标记为true。倘若此时线程正被一个sleep调用所阻塞,那么将会抛出InterruptedException
异常。
java
static boolean interrupted()
检查当前正在执行命令的线程是否被中断,需要注意的是,这一操作是通过调用一个静态方法来实现的。这个方法会产生一个副作用,即将当前线程的中断状态重置为false。
java
boolean isInterrupted()
检查线程是否已被中断,与静态的中断方法不同,这一操作不会改变线程的中断状态。
interrupt中断状态
调用线程的interrupt方法会将其中断状态设置为true,这是一个布尔类型的标志,每个线程都拥有。为了确保线程的正常运行,应定期检查此标志以确认线程是否已被中断。
java
while (Thread.currentThread().isInterrupted() && more work to do)
do more work
}
若要检测中断状态是否被触发,可首先通过调用Thread.currentThread静态方法获取当前运行的线程,随后使用isInterrupted方法来检查中断状态。
InterruptedException的作用
若线程处于阻塞状态,它将无法检测到中断信号。这正是InterruptedException
发挥作用的时候。当一个被阻塞的线程(例如,正在调用sleep
或wait
方法)上调用interrupt
方法时,这个阻塞调用将会被InterruptedException
打断,从而允许线程响应中断并作出相应处理。
注意,如果有不能被中断的阻塞I/O调用,应该考虑选择可中断的调用。
在Java的编程规范中,并没有明确要求一个被中断的线程必须终止执行。中断线程仅仅是为了提醒或引起其注意。至于如何响应这一中断,完全取决于被中断线程自身的决定。有些线程由于其重要性,即使在遇到异常后也会选择继续执行,不受中断影响,在大多数情况下,线程会将中断视为一个请求其终止的信号,并据此作出相应处理。
这种线程的run方法具有如下形式:
java
public void run()
try
while (!Thread.currentThread().isInterrupted() && more work to do)
do more work
}
catch(InterruptedException e){
thread was interrupted during sleep or wait
}finally
cleanup,if required
}
若在每轮工作迭代后都调用sleep
方法(或其他可被中断的方法),那么使用isInterrupted
进行检测就显得多余且无实际意义。原因在于,一旦中断状态被设置,并且此时调用了sleep
方法,线程将不会进入休眠状态。相反,sleep
方法会清除中断状态,并抛出InterruptedException
异常,如下所示:
java
public void run()
try{
while (more work to do){
do more work
Thread.sleep(delay);
}
}catch(InterruptedException e)
thread was interrupted during sleep
}finally{
cleanup,if required
}
因此,如果你的循环中调用了sleep
,那么无需检测中断状态。相反,你应该通过捕获InterruptedException
异常来处理中断情况.
未捕获异常处理器
线程的run
方法不允许抛出任何受检异常,未受检的异常若发生,则会导致线程结束执行。在这种情况下,线程将终止,即所谓的线程"死亡"。
对于可能传播的异常,并不需要使用catch
子句来处理。相反,在线程终止之前,异常会被传递给一个专门处理未捕获异常的处理器。这个处理器必须是属于实现了Thread.UncaughtExceptionHandler
接口的类的一个实例。该接口仅定义了一个方法,用于处理未捕获的异常。
java
void uncaughtException(Thread t.Throwable e)
setUncaughtExceptionHandler
方法,允许我们为特定线程设置一个异常处理器。此外,我们还能够利用Thread
类的setDefaultUncaughtExceptionHandler
静态方法,来为所有线程配置一个默认的异常处理器。这种机制的一个实际应用是,我们可以通过替换处理器,使用日志API将未捕获的异常报告自动发送到日志文件中,从而实现自动化的异常跟踪与记录。
设置或获取未捕获异常的默认处理器
java
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler handler);
static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler();
设置或获取未捕获异常的处理器。如果没有安装处理器,则将线程组对象作为处理器。
java
void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler handler);
Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();
如果存在父线程组,那么会调用父线程组的相应方法;若Thread类配置了默认处理器,则会调用该处理器来处理。如果这两者都不存在,系统会将异常的栈踪迹输出到标准错误流上。但需注意,若异常对象e是ThreadDeath类型(由已过时的stop方法产生),则不会打印栈踪迹。