java线程定义_Java线程基本概念

Java线程中断

在Java中,没有可以强制线程终止的方法。 然而, interrupt 方法可以用来请求终止线程。当对一个线程调用 interrupt 方法时, 线程的中断状态将被置位。

public void interrupt() {

if (this != Thread.currentThread())

checkAccess();

synchronized (blockerLock) {

Interruptible b = blocker;

if (b != null) {

interrupt0(); // Just to set the interrupt flag

b.interrupt(this);

return;

}

}

interrupt0();

}

每一个线程都具有 的 boolean 标志。 每个线程都应该不时地检査这个标志, 以判断线程是否被中断。

要想弄清中断状态是否被置位, 首先调用静态的 Thread.currentThread 方法获得当前线 程, 然后调用 islnterrupted 方法:

while (!Thread.currentThread().islnterrupted() && more work to do) {

do more work

}

如果线程被阻塞, islnterrupted方法就无法检测中断状态。这是产生 InterruptedExceptioii 异常的地 方。当在一个被阻塞的线程 (调用 sleep 或 wait ) 上调用 interrupt 方法时, 阻塞调用将会被 Interrupted Exception 异常中断。

在Thread类中,有两个非常类似的方法, interrupted 和 islnterrupted。Interrupted 方法是一个静态 方 法, 它检测当前的线程是否被中断。 而 且, 调 用 interrupted 方法会清除该线程的中断 状态。 另一方面, islnterrupted 方法是一个实例方法, 可用来检验是否有线程被中断。调 用这个方法不会改变中断状态。

public static boolean interrupted() {

return currentThread().isInterrupted(true);

}

public boolean isInterrupted() {

return isInterrupted(false);

}

中断线程的两种方法

在 catch 子句中调用 Thread.currentThread().interrupt() 来设置中断状态。于是, 方便调用者 可以对其进行检测。

try {

sleep(delay);

}catch (InterruptedException e) {

Thread.currentThreadO-interruptO;

}

用 throws InterruptedException 标记你的方法, 不采用 try 语句 块捕获异常。于是, 调用者(或者, 最终的 run 方法)可以捕获这一异常。

void mySubTaskO throws InterruptedException {

sleep(3000);

}

Java线程状态

public enum State {

NEW,RUNNABLE, BLOCKED, WAITING,TIMED_WAITING, TERMINATED;

}

线程可以有如下 6 种状态:

New (新创建)

Runnable (可运行)

Blocked (被阻塞)

Waiting (等待)

Timed waiting (计时等待)

Terminated (被终止)

要确定一个线程的当前状态, 可调用 getState 方法。

新创建线程

当用 new 操作符创建一个新线程时, 如 newThread(runable), 该线程还没有开始运行。这意味 着它的状态是 new。 当一个线程处于新创建状态时, 程序还没有开始运行线程中的代码。 在 线程运行之前还有一些基础工作要做。

可运行状态

一旦调用 start 方法, 线程处于 runnable 状态。一个可运行的线桿可能正在运行也可能没 有运行, 这取决于操作系统给线程提供运行的时间。

一旦一个线程开始运行, 它不必始终保持运行。事实上, 运行中的线程被中断, 目的是 为了让其他线程获得运行机会。 线程调度的细节依赖于操作系统提供的服务。 抢占式调度系 统给每一个可运行线程一个时间片来执行任务。当时间片用完, 操作系统剥夺该线程的运行 权, 并给另一个线程运行机会。当选择下一个线程时, 操作系统考虑线程的优 先级。

现在所有的桌面以及服务器操作系统都使用抢占式调度。在具有多个处理器的机器上,每一个处理器运行一个线程, 可以有多个线程并行运行。 当然, 如果线程的数目多于处理器的数目, 调度器依然采用时间片机制。

被阻塞状态

当一个线程试图获取一个内部的对象锁(而不是 javiutiUoncurrent 库中的锁,) 而该 锁被其他线程持有, 则该线程进人阻塞状态。 当所有其他线程释放该锁, 并且线程调度器允许 本线程持有它的时候, 该线程将变成非阻塞状态。

等待状态

当线程等待另一个线程通知调度器一个条件时, 它自己进入等待状态。 在调用 Object.wait 方法或 Thread.join 方法, 或者是等待 java, util.concurrent 库中的 Lock 或 Condition 时, 就会出现这种情况。实际上, 被阻塞状态 与等待状态是有很大不同的。

public final void wait() throws InterruptedException {

wait(0);

}

public final void join() throws InterruptedException {

join(0);

}

join方法是等待另一个线程执行的结束,而wait方法则是需要别的线程调用notify或者notifyAll,然后根据线程的优先级选择。

public final native void notify();

public final native void notifyAll();

计时等待

有几个方法有一个超时参数。 调用它们导致线程进人计时等待(timed waiting) 状 态。 这一状态将一直保持到超时期满或者接收到适当的通知。 带有超时参数的方法有 Thread.sleep 和 Object.wait、Thread.join、Lock,tryLock 以及 Condition.await 的计时版。

public static native void sleep(long millis) throws InterruptedException;

public final native void wait(long timeout) throws InterruptedException;

public final synchronized void join(long millis)

throws InterruptedException {

long base = System.currentTimeMillis();

long now = 0;

if (millis < 0) {

throw new IllegalArgumentException("timeout value is negative");

}

if (millis == 0) {

while (isAlive()) {

wait(0);

}

} else {

while (isAlive()) {

long delay = millis - now;

if (delay <= 0) {

break;

}

wait(delay);

now = System.currentTimeMillis() - base;

}

}

}

被终止状态

线程因如下两个原因之一而被终止:

因为 run 方法正常退出而自然死亡。

因为一个没有捕获的异常终止了 run 方法而意外死亡。

84dc9e33de5f337d3df539192c9d85da.png

线程属性

线程优先级

在 Java 程序设计语言中, 每一个线程有一个优先级。 默认情况下, 一+线程继承它的父 线程的优先级。 可以用 setPriority 方法提高或降低任何一个线程的优先级。 可以将优先级设 置为在 MIN_PRIORITY ( 在 Thread 类中定义为 1 ) 与 MAX_PRIORITY ( 定义为 10 ) 之间的 任何值。NORM_PRIORITY 被定义为 5。

/**

* The minimum priority that a thread can have.

*/

public final static int MIN_PRIORITY = 1;

/**

* The default priority that is assigned to a thread.

*/

public final static int NORM_PRIORITY = 5;

/**

* The maximum priority that a thread can have.

*/

public final static int MAX_PRIORITY = 10;

每当线程调度器有机会选择新线程时, 它首先选择具有较高优先级的线程。 但是, 线程 优先级是高度依赖于系统的。当虚拟机依赖于宿主机平台的线程实现机制时, Java 线程的优 先级被映射到宿主机平台的优先级上, 优先级个数也许更多, 也许更少。

public static native void yield();

导致当前执行线程处于让步状态。 如果有其他的可运行线程具有至少与此线程同样高 的优先级, 那么这些线程接下来会被调度。 注意, 这是一个静态方法。

守护线程

可以调用

// 判断一个线程是否为守护线程

public final boolean isDaemon() {

return daemon;

}

public final void setDaemon(boolean on) {

checkAccess();

if (isAlive()) {

throw new IllegalThreadStateException();

}

daemon = on;

}

将线程转换为守护线程(daemon thread。) 这样一个线程没有什么神奇。守护线程的唯一用途 是为其他线程提供服务。计时线程就是一个例子, 它定时地发送“ 计时器嘀嗒” 信号给其他 线程或清空过时的高速缓存项的线程。当只剩下守护线程时, 虚拟机就退出了,由于如果只 剩下守护线程, 就没必要继续运行程序了。

未捕获异常处理器

线程的 run 方法不能抛出任何受查异常, 但是, 非受査异常会导致线程终止。 在这种情 况下, 线程就死亡了。

public abstract void run(); // 没有抛出任何任何异常

但是, 不需要任何 catch 子句来处理可以被传播的异常。 相反, 就在线程死亡之前, 异 常被传递到一个用于未捕获异常的处理器。该处理器必须属于一个实现 Thread.UncaughtExceptionHandler 接口的类。 这个接口只有 —个方法。

public interface UncaughtExceptionHandler {

void uncaughtException(Thread t, Throwable e);

}

可以用 setUncaughtExceptionHandler 方法为任何线程安装一个处理器。 也可以用 Thread 类的静态方法 setDefaultUncaughtExceptionHandler 为所有线程安装一个默认的处理器。 替换 处理器可以使用日志 API 发送未捕获异常的报告到日志文件。

public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {

checkAccess();

uncaughtExceptionHandler = eh;

}

public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {

SecurityManager sm = System.getSecurityManager();

if (sm != null) {

sm.checkPermission(

new RuntimePermission("setDefaultUncaughtExceptionHandler")

);

}

defaultUncaughtExceptionHandler = eh;

}

如果不安装默认的处理器, 默认的处理器为空。 但是, 如果不为独立的线程安装处理 器, 此时的处理器就是该线程的 ThreadGroup 对象。

public class ThreadGroup implements Thread.UncaughtExceptionHandler {

// ThreadGroup实现的未捕获异常的处理器

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);

}

}

}

}

ThreadGroup 类实现 Thread.UncaughtExceptionHandler 接口。 它的 uncaughtException 方 法做如下操作:

如果该线程组有父线程组, 那么父线程组的 uncaughtException 方法被调用。

否则, 如果 Thread.getDefaultExceptionHandler 方法返回一个非空的处理器, 则调用 该处理器。

否则, 如果 Throwable 是 ThreadDeath 的一个实例, 输出异常出现的线程名字。

否则, 线程的名字以及 Throwable 的栈轨迹被输出到 System.err 上。

这是你在程序中肯定看到过许多次的栈轨迹.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值