并发,指的是在一段时间内,多个任务近似地在同时运行,也就是时间宏观上的并行。
实现多线程编程,需要实现Runnable接口或继承Thread类(不推荐,成本较实现接口更高,灵活性更低)。Runnable和Thread中都有一个run()方法,是需要子类进行实现的。当实例化一个进程对象时,Thread.run()只是调用了run()方法,Thread.start()才是开启这个线程的正确方式。
线程状态
线程可以有六个状态:New、Runnable、Blocked、Waiting、Timed waiting、Terminated。可以通过getState()方法查看。
New(新创建线程):当使用new操作符,创建一个线程对象时,线程处于新创建状态,在可以运行前还有一些准备工作要做。
Runnable(可运行状态):调用start()方法时,线程处于可运行状态,但该状态的线程可能在运行也可能还没开始运行。
Blocked(阻塞):线程请求得到某个同步资源时,而该资源正在被其他线程占有,此时进入阻塞态。
Waiting(等待):Timed waiting(计时等待):等待另一个线程通知调度器一个条件时,进入等待态,当调用某些带有超时参数的等待方法,线程就进入计时等待状态。阻塞态与等待态还是有很大不同的。
Terminated(终止):1、线程完成任务,正常终止;2、因为一个没有捕获的异常终止了run方法,异常死亡。
线程属性
线程优先级
每个线程都有优先级,可以通过setPriority进行设置。java默认线程优先级在MIN_PRIORITY(1)到MAX_PRIORITY(10)之间。NORM_PRIORITY被设置为5。但需要注意的是,线程的优先级是高度依赖宿主机系统的。比如Windows系统有7个优先级别,Linux系统中每个线程优先级相同。因此虚拟机在对应不同系统时,应该将这10个级别映射到宿主机的线程优先级别上。
守护线程
通过调用setDaemon(true)将该线程设置成守护线程。守护线程唯一的用途是为其他线程提供服务。例如计时线程,为其他线程提供计时时钟。当只剩下守护线程时,虚拟机就退出了。应当注意,守护线程不应该访问任何系统资源,因为守护线程可能会在任何时刻发生中断。
未捕获异常处理器
线程的run方法不可以抛出任何受查异常。但,非受查异常又会导致线程异常死亡。在线程死亡前,异常会被传递到一个用于未捕获异常的处理器。可以用setUncaughtExceptionHandler方法为任何线程安装处理器。或者用静态方法setDefaultUncaughtExceptionHandler配置默认处理器。若不单独配置处理器,则该线程的处理器就是它的线程组对象(线程组已过时)。