资讯专栏INFORMATION COLUMN

Java多线程之线程的创建、中断、状态与属性

liangdas / 479人阅读

摘要:中断线程当线程的方法方法体执行完毕自然终止或在方法中出现没有捕获的异常时意外终止,线程将终止。如果被中断线程被阻塞,就无法检测中断状态,就会产生异常。

多进程与多线程的本质区别在于:每个进程拥有自己的一整套变量,而线程则共享数据。如果需要执行一个比较耗时的任务,应该使用独立的线程。

可以通过实现Runnable接口或继承Thread类来创建独立的线程。

1) 实现Ruannable接口

class MyRunnable implements Runnable {
    public void run() {
        task code
    }
}
Ruannable r = new MyRuannable();
Thread t = new Thread(r);
t.start();

2) 继承Thread

class MyThread extends Thread {
    public void run() {
        task code
    }
}
Thread t = new MyThread();
t.start();

对于Thread类或Runnable对象,启动新线程调用的是start()方法,直接调用run()方法只会在同一个线程中执行任务。start()会启动这个线程,引发调用run()方法。start()方法会立即返回,并且新线程并行运行。

如果有很多任务,为每个任务创建一个独立的线程付出的代价太大,可以使用线程池来解决这个问题。

中断线程

当线程的run()方法方法体执行完毕(自然终止)或在方法中出现没有捕获的异常时(意外终止),线程将终止。另外,可以使用interrupt()方法发送中断请求强制线程终止。

每个线程都有boolean标志的中断状态位,想弄清当前线程是否被中断(中断状态位是否被置位),需要当前线程自己判断。并且,被中断的线程可以决定如何响应中断。如果被中断线程被阻塞,就无法检测中断状态,就会产生InterruptedException异常。

public void run() {
    try {
        do some work
        while(! Thread.currentThread().isInterrupted() && more work to do) {
            do more work
        }
    } catch(InterruptedException e) {
        // thread was interrupted during sleep or wait (in blocked)
    } finally {
        cleanup if required
    }
}

当产生异常时,有两种处理方式选择。

1) 在catch子句中设置中断状态。

catch(InterruptedException e) {
    Thread.currentThread().interrupt();
}

2) 不采用try语句块捕获异常,交给调用者处理。

void mySubTask() throws InterruptedException {}

测试当前线程是否被中断有interrupted()isInterrupted()两个方法。
interrupted()是一个静态方法,有副作用,会把中断状态位置为false
isInterrupted()是一个实例方法,无副作用。

线程状态

线程有6种状态,可以调用getState()获取线程状态。

New:新创建状态,在可运行前还有些工作要做;

Runnable:可运行状态,可能正在运行也可能没有运行,是否运行需看操作系统调度;

Blocked:被阻塞状态,不活动,可能由于请求锁失败;

Waiting:等待状态,不活动,等待通知,比如调用Thread.join()方法;

Timed Waiting:计时等待状态,不活动,等待超时或通知,比如调用Thread.sleep(long millis)join(long millis)方法;

Terminated:被终止状态,线程可能由于自然死亡或意外死亡。

线程属性 线程优先级

每一个线程都有一个优先级,默认继承父线程。注意,不要将程序功能的正确性依赖于优先级。可以通过setPriority(int newPriority)方法设置线程优先级,最小优先级MIN_PRIORITY为1,默认优先级NORM_PRIORITY为5,最高优先级MAX_PRIORITY为10。

当操作系统的线程调度器有机会选择新线程时,会首先选择拥有较高优先级的线程。调用Thread类的静态方法yield()可使当前执行线程处于让步状态,如果有可运行的线程优先级大于等于此线程,那么这些线程将被调度。

守护线程

守护线程的唯一用途是为其他线程提供服务,通过调用t.setDaemon(true)将线程转化为守护线程。如果只剩下守护线程,虚拟机就会退出。

注意,守护线程应该永远不去访问固有资源,因为这些操作可能会发生中断。

未捕获异常处理器

线程的run()方法不能抛出任何被检测的异常,但可能会抛出不被检测的异常,导致线程终止。就在线程死亡之前,异常被传递到未捕获异常处理器,进行处理,比如使用日志API发送异常到日志文件。

class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
    void uncaughtException(Thread t, Throwable e) {
        // t - terminated thread without exception catch
        // e - uncaught exception object
        do something like send exception info to log file
    }
}

为线程设置处理器可通过方法setUncaughtExceptionHandler()或静态方法setDefaultUncaughtExceptionHandler()完成。如果不设置未捕获异常处理器,那么默认处理器为空。

方法getUncaughtExceptionHandler()用于获取未捕获异常处理器,但是有副作用,如果返回值为空,那么就会将ThreadGroup对象设置为处理器。线程组ThreadGroup对象的执行流大致如下:

if(该线程组有父线程组) {
    父线程组的uncaughtException方法被调用
} else {
    if(Thread.getDefaultExceptionHandler()返回非空处理器) {
        调用该处理器
    } else {
        if(Throwable是ThreadDeath的一个实例) {
            // 由过时方法stop产生
            什么都不做
        } else {
            输出栈踪迹到标准错误流
        }
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65744.html

相关文章

  • Java线程进阶(六)—— J.U.Clocks框架:AQS综述(1)

    摘要:在时,引入了包,该包中的大多数同步器都是基于来构建的。框架提供了一套通用的机制来管理同步状态阻塞唤醒线程管理等待队列。指针用于在结点线程被取消时,让当前结点的前驱直接指向当前结点的后驱完成出队动作。 showImg(https://segmentfault.com/img/remote/1460000016012438); 本文首发于一世流云的专栏:https://segmentfau...

    cocopeak 评论0 收藏0
  • (一)java线程Thread

    摘要:本人邮箱欢迎转载转载请注明网址代码已经全部托管有需要的同学自行下载类学习线程的开发者首先遇到的第一个类就是通过使用类我们就可以启动停止中断一个线程在同一个时间片里可能会有多个线程在执行每个线程都拥有它自己的方法调用堆栈参数和变量每个至少会有 本人邮箱: 欢迎转载,转载请注明网址 http://blog.csdn.net/tianshi_kcogithub: https://github...

    boredream 评论0 收藏0
  • Java 线程核心技术梳理(附源码)

    摘要:本文对多线程基础知识进行梳理,主要包括多线程的基本使用,对象及变量的并发访问,线程间通信,的使用,定时器,单例模式,以及线程状态与线程组。源码采用构建,多线程这部分源码位于模块中。通知可能等待该对象的对象锁的其他线程。 本文对多线程基础知识进行梳理,主要包括多线程的基本使用,对象及变量的并发访问,线程间通信,lock的使用,定时器,单例模式,以及线程状态与线程组。 写在前面 花了一周时...

    Winer 评论0 收藏0
  • Java线程笔记(一):JMM基础关键字

    摘要:当线程执行完后进入状态,表示线程执行结束。其中和表示两个线程。但要注意,让出并不表示当前线程不执行了。关键字其作用是防止指令重排和使线程对一个对象的修改令其他线程可见。 JMM特性一览 Java Memory Model的关键技术点都是围绕着多线程的原子性、可见性和有序性来建立的。因此我们首先需要来了解这些概念。 原子性(Atomicity) 原子性是指一个操作是不可中断的。即使是在多...

    cyixlq 评论0 收藏0
  • java线程Thread类

    摘要:实现接口直接被继承的子类是程序中的执行线程,虚拟机允许应用程序同时运行多个执行线程。如果要恢复目标线程的线程试图在调用之前锁定此监视器,则会导致死锁。线程可以拥有的最大优先级。 Class Thread java.lang.Object java.lang.Thread 实现接口:Runnable直接被继承的子类:ForkJoinWorkerThread public cl...

    jzzlee 评论0 收藏0

发表评论

0条评论

liangdas

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<