java中的interrupt(),InterruptException和wait(),sleep()

标题中的几个概念大概设计到线程同步以及线程阻塞这两个概念。线程同步,就是同一时刻,只有一个线程能执行指定的代码;另外一个线程阻塞就是当前线程暂时停在某个位置,等待某个条件成立之后再继续往下面执行。

线程同步就是,是为了控制多线程工作存在的并发造成共享资源竞争的问题。java中可以通过加锁(monitor)的方式来控制,其实就是两个关键字,一个是synchronized,另外一个是lock,关于这两个的区别,请自行google。其中wait方法就必须获取某个对象的monitor之后,才允许执行,否则会跑出monitor status不正确的异常。wait()和join()方法是属于Object的实例方法。wait()方法必须放在同步代码块之内(如下),即是表示获得了某个对象的monitor(锁)之后,才允许执行该对象的wait()方法;执行了wait()方法之后,当前线程会处于阻塞状态,这时候当前线程会释放进来的时候获取的指定对象的monitor(锁),同时让出cpu,不在参与cpu的竞争,等待其他线程执行指定对象的notify()或者notifyAll()方法来将其唤醒,以继续执行下去(被唤醒之后,也要先获取指定对象的锁才会进来,因为同步块进来之前必须是获取了指定对象的monitor,同时,不是从新执行,获得monitor之后,是从之前wait()那里开始继续网下面执行,因为之前在这里阻塞了,cpu相关的寄存在会记住之前阻塞的位置的)。

public class Service {
    public void testMethod(Object lock) {
        try {
            synchronized (lock) {
                System.out.println("begin wait() ThreadName=" + Thread.currentThread().getName());
                lock.wait();
                if (Thread.currentThread().getName().equals("Thread-1")) {
                    Thread.sleep(50000);
                }
                System.out.println("end wait() ThreadName=" + Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void synNotifyMethod(Object lock) {
        synchronized (lock) {
            System.out.println("begin notify() ThreadName=" + Thread.currentThread().getName());
            lock.notifyAll();
            System.out.println("end notify() ThreadName=" + Thread.currentThread().getName());
        }
    }
}

至于interrupt()方法和InterruptException异常,是java专门用来处理线程阻塞的。线程阻塞,就表示要等待一段时间。如果需要等待的时间比较长,正常还没结束之前想中断某个线程的阻塞状态怎么办?这就是靠interrupt()方法来解决了。如果因为一些特殊的原因,想提前中断一些阻塞的线程,以让他们提前解除阻塞状态,然后继续执行下去。只需要在其他线程调用指定线程的interrupt()方法即可(interrupt()方法是线程实例方法),这时候原来阻塞的对应的线程就会抛出InterruptException异常,通过catch捕获异常就可以继续往下面执行了。比如线程方法sleep()和Object的实例方法wait(),都会导致当前线程阻塞,这时候就可以通过interrupt()方法来提前退出阻塞状态。

为什么Interrupt()方法可以提前中断阻塞呢?其实是因为每个线程都会有一个中断状态位,暂且叫做interruptStatus吧。当前执行sleep()和wait()这些方法的时候,当前线程会把该interrruptStatus状态位设置为true,以标识当前线程为阻塞状态。当调用该线程的Interrupt()方法的话,就会重置interruptStatus状态为为false。而sleep()和wait()方法内部会不断地轮询检查InterruptStatus状态值,如果某一时刻变为false的时候,当前线程就会中断阻塞状态,通过抛出InterrupException的方式来中断阻塞状态,然后继续执行下去。

至于wait()方法和notify()的关系,通过另外一篇文章来讲述吧。

来自为知笔记(Wiz)

时间: 2024-11-09 09:47:53

java中的interrupt(),InterruptException和wait(),sleep()的相关文章

java中线程的取消

Java中没有一种安全的抢占式方法来停止线程,只有一种协作式的机制. 大致分为两种协作式机制:1.设置某个"已请求取消"的标志,线程任务定期查看该标志.如果取消标志设置为true,则结束任务 2.调用线程的interrupt()能中断目标线程,通过Thread.currentThread().isInterrupted()方法来查询,也可以通过大多数可阻塞的库函数(如Thread.sleep和Object.wait)来抛出InterruptedException异常,在异常中退出线程.

Java中如何优雅正确的终止线程

Java中终止线程的方式主要有三种: 1.使用stop()方法,已被弃用.原因是:stop()是立即终止,会导致一些数据被到处理一部分就会被终止,而用户并不知道哪些数据被处理,哪些没有被处理,产生了不完整的"残疾"数据,不符合完整性,所以被废弃.So, forget it! 2.使用volatile标志位 看一个简单的例子: 首先,实现一个Runnable接口,在其中定义volatile标志位,在run()方法中使用标志位控制程序运行 public class MyRunnable i

Java中的线程池

综述 在我们的开发中经常会使用到多线程.例如在Android中,由于主线程的诸多限制,像网络请求等一些耗时的操作我们必须在子线程中运行.我们往往会通过new Thread来开启一个子线程,待子线程操作完成以后通过Handler切换到主线程中运行.这么以来我们无法管理我们所创建的子线程,并且无限制的创建子线程,它们相互之间竞争,很有可能由于占用过多资源而导致死机或者OOM.所以在Java中为我们提供了线程池来管理我们所创建的线程. 线程池的使用 采用线程池的好处 在这里我们首先来说一下采用线程池的

Java中的多线程

对于直接继承Thread的类来说,代码大致框架是: 1 2 3 4 5 6 7 8 9 10 11 12 class 类名 extends Thread{ 方法1; 方法2: … public void run(){ // other code… } 属性1: 属性2: … } 先看一个简单的例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 /**  * @author Rollen-Ho

Java中的多线程你只要看这一篇就够了

Java中的多线程你只要看这一篇就够了 引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其实只有一半对,因为反应"多角色"的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的"生产者,消费者模型". 很多人都对其中的一些概念不够明确,如同步.并发等等,让我

编程思想之多线程与多进程(2)——Java中的多线程

原文:http://blog.csdn.net/luoweifu/article/details/46673975 作者:luoweifu 转载请标名出处 <编程思想之多线程与多进程(1)--以操作系统的角度述说线程与进程>一文详细讲述了线程.进程的关系及在操作系统中的表现,这是多线程学习必须了解的基础.本文将接着讲一下Java中多线程程序的开发 单线程 任何程序至少有一个线程,即使你没有主动地创建线程,程序从一开始执行就有一个默认的线程,被称为主线程,只有一个线程的程序称为单线程程序.如下面

《java并发编程实战》读书笔记4--基础构建模块,java中的同步容器类&amp;并发容器类&amp;同步工具类,消费者模式

上一章说道委托是创建线程安全类的一个最有效策略,只需让现有的线程安全的类管理所有的状态即可.那么这章便说的是怎么利用java平台类库的并发基础构建模块呢? 5.1 同步容器类 包括Vector和Hashtable,此外还包括在JDK1.2中添加的一些功能相似的类,这些同步的封装器类由Collections.synchronizedXxx等工厂方法创建的.这些类实现线程安全的方式是:将他们的状态封装起来,并对每个共有方法都进行同步,使得每次只能有一个线程能访问容器的状态. 关于java中的Vect

[转]Java中的多线程你只要看这一篇就够了

如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其实只有一半对,因为反应“多角色”的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的“生产者,消费者模型”. 很多人都对其中的一些概念不够明确,如同步.并发等等,让我们先建立一个数据字典,以免产生误会. 多线程:指的是这个程序(一个进程)运

线程基础:线程(3)——JAVA中的基本线程操作(中)

(接上文<线程基础:线程(2)--JAVA中的基本线程操作(上)>) 1-4.注意synchronized关键字的使用 在前面的文章中我们主要讲解的是线程中"对象锁"的工作原理和操作方式.在讲解synchronized关键字的时候,我们还提到了synchronized关键字可以标注的位置.大家经常看到相当部分的网贴,在它们的代码示例中将synchronized关键字加载到代码的方法体上,然后告诉读者:这个操作是线程安全的.代码可能如下: /** * 这个类的class对象进