Thread (core java)

创建线程

建议不要通过构建Thread子类对象,并调用start方法。应该从运行机制上减少需要并行运行的任务数量。如果有很多任务,要为每个任务创建一个独立的线程付出的代价太大,可以使用线程池来解决这个问题。(参考14.9)

java.lang.Thread

  1. Thread(Runnable target) 构造一个新线程用于调用给定target的run方法。
  2. void start() 启动此线程,将引发调用run()方法,这个方法会立即返回,并且新线程将并行运行。
  3. void run() 调用关联Runnable的run方法。

java.lang.Runnable

  1. void run() 必须覆盖这个方法,并在这个方法中提供所需要执行的任务指令。

中断线程

早期java使用stop()方法可以强制线程中止,现在已经被弃用;
interrupt() 方法可以用来请求中止线程。但是如果线程被阻塞,就无法检测中断状态。这是产生InterruptedException异常的地方,当在一个被阻塞的线程(调用sleep或wait)上调用interrupt方法时,阻塞调用将会被InterruptedException异常中断,这里指会进入catch代码块执行(存在不能被中断的阻塞I/O调用,应该考虑选择可中断的调用。细节参考卷二 第一章和第三章)
java.lang.Thread

  1. void interrupt() 向线程发送中断请求,线程的中断状态将被设置为true.
    如果目前线程被一个sleep调用阻塞,那么InterruptedException异常被抛出,此外中断状态将被清除
  2. static boolean interrupted() 测试正在执行这一方法的线程是否被中断,注意这是一个静态方法,调用会产生副作用,它将当前线程的中断状态重置为false.(线程的中断状态被清除)
  3. boolean isInterrupted() 测试线程是否终止,不像静态的中断方法,这一调用不改变线程的中断状态。
  4. static Thread currentThread() 返回代表当前执行线程的Thread对象。
  5. static void sleep(long millis) 休眠给定的毫秒数

void interrupt() 中断此线程。(谷歌翻译)
线程用一个变量来标志中断状态,private volatile Interruptible blocker;
除非当前线程正在中断自身(始终允许),否则将调用此线程的checkAccess方法,这可能导致抛出SecurityException。
如果在调用Object类的wait(),wait(long)或wait(long,int)方法或者join(),join(long),join(long,int)的方法中阻塞了这个线程,sleep(long)或sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到InterruptedException。
如果此线程在可中断通道上的I / O操作中被阻塞,则通道将被关闭,线程的中断状态将被设置,并且线程将收到ClosedByInterruptException。
如果此线程在Selector中被阻塞,则线程的中断状态将被设置,并且它将立即从选择操作返回,可能具有非零值,就像调用选择器的唤醒方法一样。
如果以前的条件都不成立,则将设置该线程的中断状态。
中断不活动的线程不会产生任何影响。

public class TestRun implements Runnable {
    private boolean flag = true;

    @Override
    public void run() {
        try {
            while (!Thread.currentThread().isInterrupted() && flag) {
                // do more work
                Thread.currentThread().sleep(1000);
            }
        }
        catch (InterruptedException e) {
            // thread was interrupted during sleep or wait
            
        }
        finally {
            //cleanup,if required
        }
        //exiting the run method terminates the thread
    }
    
    void mySubTask() {
        try {
            Thread.currentThread().sleep(1000);
        }
        catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    void mySubTask2() throws InterruptedException {
        Thread.currentThread().sleep(1000);
    }
}

线程状态

  1. 新建 New
    new Thread(r)/new MyThread()
  2. 可运行 Runnable
    thread.start()
    (抢占式调度系统;协作式调度系统中,一个线程只有在调用yield方法或者被阻塞或等待时,线程才会失去控制权)
    任何时刻,一个可运行的线程可能正在运行,也可能没有运行
  3. 被阻塞 Blocked
    一个线程试图获取一个内部对象锁,而该锁被其它对象持有,则线程进入阻塞状态。
  4. 等待 Waiting/ 计时等待 Timed waiting
    Thread.sleep
    Object.wait
    Thread.join
    Lock.tryLock
    Condition.await
  5. 被中止 Terminated
    因为run方法正常退出而自然死亡
    因为一个没有捕获的异常中止了run方法而意外死亡
    stop方法已过时,不要在代码中使用
  6. 相关的API
    java.lang.Thread

6.1void join():等待中止指定的线程即等待指定的线程终止后再继续当前线程
6.2void join(long millis):等待指定的线程死亡,或者经过指定的毫秒数
6.3Thread.State getState():获取线程的状态
6.4void stop():停止线程,已过时
6.5void suspend:暂停线程执行,已过时
6.6void resume:调用suspend之后调用,已过时

线程属性

  1. 优先级
    高优先级只代表线程优先获取时间片的可能性比较大,不是必然
  2. API
    java.lang.Thread

2.1void setPriority(int newPriority):设置优先级,必须在Thread.MIN_PRIORITY与Thread.MAX_PRIORITY之间,一般使用Thread.NORM_PRIORITY优先级。
2.2static int MIN_PRIORITY:线程最小优先级1.
2.3static int MAX_PRIORITY:线程最大优先级10.
2.4static int NORM_PRIORITY:线程默认优先级5.
2.5static void yield():导致当前执行线程处于让步状态,如果有其他可运行的线程具有至少与此线程同样高的优先级,那么这些线程接下来会被调度。注意,这是一个静态方法。

3.守护线程/API
3.守护线程优先级很低,当同一应用程序中没有其他线程在运行的时候,守护线程才运行。当守护线程是程序中唯一运行的线程时,守护线程执行结束后,JVM也就结束了这个程序。
3.2守护线程的作用:通常作为同一程序中普通线程的服务提供者,它们通常是无限循环的,以等待服务请求或者执行线程的任务。此外我们不太可能知道守护线程什么时候能够获取CPU时钟,并且没有其它线程运行的时候,守护线程随时可能结束。一个典型的守护线程是Java的垃圾回收器。
java.lang.Thread

3.3void setDaemon(boolean isDaemon):标识该线程为守护线程或用户线程。这一方法必须在线程启动之前调用

4未捕获异常处理器
4.1未捕获异常处理器介绍
线程的run方法不能抛出任何被检测的异常,但是,不被检测的异常会导致线程终止。在这种情况下,线程就死亡了。就作线程死亡之前,异
常被传递到一个用于未捕获异常的处理器。
该处理器必须属于一个实现Thread.UncaughtExceptionHandler接口的类。
这个接口只有一个方法。
void uncauqhtException(Thread t, Throwable e)
可以用 setUncaughtExceptionHandler方法为任何线程安装一个处理器。也可以用 Thread类的静态方法setDefaultUncaughtExceptionHandlcr为所有线程安装一个默认的处理器。如果不安装默认的处理器,默认的处理器为空。但是,如果没有设置UncaughtExceptionHandler,那么默认将会把异常栈信息输出到System.err,此时的处理器就足该线程的ThreadGroup对象

线程组是一个可以统一管理的线程集合。默认情况下,创建的所有线程属于相同的线程组,但是,也可能会建立其他的组。现在引入了更好的特性用于线程集合的操作,所以建议不要在自己的程序中使用线程组。
ThreadGroup 类实现 Thread.UncaughtException 接口。它的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();
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }

4.2相关API
java.lang.Thread
4.2.1 public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler)
4.2.2 public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
4.3.3 public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
4.4.4 public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()

java.lang.Thread.UncaughtExceptionHandler
4.2.5 void uncaughtException(Thread t,Throwable e)当给定线程因给定的未捕获异常而终止时,调用该方法。 Java 虚拟机将忽略该方法抛出的任何异常。

java.lang.ThreadGroup
4.2.6 public void uncaughtException(Thread t,Throwable e)当此线程组中的线程因为一个未捕获的异常而停止,并且线程没有安装特定 Thread.UncaughtExceptionHandler 时,由 Java Virtual Machine 调用此方法。

ThreadGroup 的 uncaughtException 方法执行以下操作:
1.如果此线程组有一个父线程组,那么调用此父线程组的 uncaughtException 方法时带有两个相同的参数。
2.否则,此方法将查看是否安装了默认的未捕获异常处理程序,如果是,则在调用其 uncaughtException 方法时带有两个相同的参数。
3.否则,此方法将确认 Throwable 参数是否为一个 ThreadDeath 实例。如果是,则不会做任何特殊的操作。否则,在从线程的 getName 方法返回时,会使用 Throwable 的 printStackTrace 方法,将包含线程名称的消息和堆栈跟踪信息输出到标准错误流。
应用程序可以重写 ThreadGroup 的子类中的方法,以提供处理未捕获异常的替代办法。

线程同步

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 2,110评论 0 14
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 2,957评论 1 18
  • 一、wait--notify--sleep Object obj = new Object(); obj.wait...
    fe0180bd6eaf阅读 335评论 0 1
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,454评论 1 15
  • 很多人受到大的打击就会一蹶不振,从此没有了生机。今天学到了一个新的原因,很合理,就是因为自恋。 大概意思就是这种人...
    Universe2018阅读 204评论 0 0