Java中断线程的方法
2016-10-25 13:38
246 查看
线程的基本概念
什么是线程
线程是操作系统能夠進行運算调度的最小單位。 它被包含在进程之中,是行程中的實際運作單位。 一条线程指的是进程中一个单一顺序的控制流,一個进程中可以並行多個线程,每条线程并行执行不同的任务。共享和可变
要编写线程安全的代码,其核心在于对共享的和可变的状态进行访问。“共享”就意味着变量可以被多个线程同时访问。我们知道系统中的资源是有限的,不同的线程对资源都是具有着同等的使用权。有限、公平就意味着竞争,竞争就有可能会引发线程问题。
“可变”是指变量的值在其生命周期内是可以发生改变的。“可变”对应的是“不可变”。我们知道不可变的对象一定是线程安全的,并且永远也不需要额外的同步(因为一个不可变的对象只要构建正确,其外部可见状态永远都不会发生改变)。所以“可变”意味着存在线程不安全的风险。解决办法:
1、不在线程中共享该状态变量,可以将变量封装到方法中。
2、将状态变量修改为不可变的变量(final)。
3、访问状态变量时使用同步策略。
4、使用原子变量类。
线程安全性
线程安全是一个比较复杂的概念。其核心概念就是正确性。所谓正确性就是某各类的行为与其规范完全一致,即其近似与“所见即所知(we know it when we see it)”。当多个线程访问某各类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。线程同步
线程通过其核心就在于一个“同”。所谓“同”就是协同、协助、配合,“同步”就是协同步调昨,也就是按照预定的先后顺序进行运行,即“你先,我等, 你做完,我再做”。线程同步,就是当线程发出一个功能调用时,在没有得到结果之前,该调用就不会返回,其他线程也不能调用该方法。就一般而言,我们在说同步、异步的时候,特指那些需要其他组件来配合或者需要一定时间来完成的任务。在多线程编程里面,一些较为敏感的数据时不允许被多个线程同时访问的,使用线程同步技术,确保数据在任何时刻最多只有一个线程访问,保证数据的完整性。
线程同步的机制主要有:临界区、互斥量、事件、信号量四种方式
1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。
2、互斥量:采用互斥对象机制。
只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享。
4、事 件: 通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作。
原子性
原子是世界上最小的单位,具有不可分割性。在我们编程的世界里,某个操作如果不可分割我们就称之为该操作具有原子性。例如:i = 0,这个操作是不可分割的,所以该操作具有原子性。如果某个操作可以分割,那么该操作就不具备原子性,例如i++。非原子操作都存在线程安全问题,这个时候我们需要使用同步机制来保证这些操作变成原子操作,来确保线程安全。可见性
线程可见性是指线程之间的可见性,即一个线程对状态的修改对另一个线程是可见的,也就是一个线程修改的结果,另外一个线程立马就知道了。比如volitile修饰的变量,就具备可见性。有序性
有序性指的是数据不相关的变量在并发的情况下,实际执行的结果和单线程的执行结果是一样的,不会因为重排序的问题导致结果不可预知。volatile, final, synchronized,显式锁都可以保证有序性。Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!
现在,如果你要安全有效地终止一个线程,应该采用以下这些方法:
线程中断的方法
线程正常执行完毕,正常结束。
也就是让run方法执行完毕,该线程就会正常结束。监控某些条件,结束线程的不间断运行
然而,常常有些线程是伺服线程。它们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。通常,它们执行在一个while(true)的死循环中。
如:
@Override publicvoid run() { while(true){ someWork(); if(finished){ break; } try { Thread.sleep(10000); } catch (InterruptedException e) { /* TODO自动生成 catch 块 * */ e.printStackTrace(); } } }
我们可以在while死循环内,每次循环时,察看外部条件,看看是否需要关闭当前线程。如果是,就break,跳出死循环,或者是抛出异常,跳出死循环,结束线程。
捕获InterruptedException 运行时异常,中断当前线程。
有些执行伺服任务的线程,在while(true)这样的死循环内部,是一个阻塞中的方法。此时,就不能采用第二种方法了。因为,当该方法没有返回时,该线程一直处于阻塞当中,根本无法执行其他语句。此时,就需要调用该线程的interrupt方法,产生一个InterruptedException运行时异常,是阻塞中的那个方法抛出这个异常,从而让我们有机会结束这个线程的执行。
如:
@Override publicvoid run() { while(true){ try { // getSendMessages 是BlockingQueue类。它的take方法将会阻塞! responseMessage = this.getSendMessages().take(); } catch (InterruptedException e1) { thrownew RuntimeException(); //或者break; } someWork(); }
一个外部的Thread 对象 指向这个线程。 需要结束这个线程时,只需要调用thread对象的interrupt() 方法,就会在
responseMessage = this.getSendMessages().take();
这条语句中产生一个InterruptedException异常,从而结束该线程的阻塞状态,通过抛出异常,或者break跳出死循环,结束这个线程。
相关文章推荐
- java 线程的中断interrupt方法
- java线程中断,interrupt()方法的一些示例
- Java之多线程interrupt中断线程的三种方法
- java线程中断方法
- java线程基础巩固---Thread中断Interrupt方法学习&采用优雅的方式结束线程生命周期
- Java中断线程的方法
- Java学习笔记78. 线程的中断入门 —— interrupt方法
- Java多线程-通过线程的中断来深入学习interrupt方法,Volatile关键字
- JAVA中断线程的方法
- Java中实现线程的超时中断方法实例
- JAVA中断线程的方法
- Java中断线程的方法
- Java 中断线程方法
- JAVA中断线程的方法
- JAVA多线程-生产者与消费者当线程多时发生死锁的解决方法
- 在Java中实现线程的两种方法
- 一个方法最多2个线程同时使用的JAVA实现
- 开发笔记:创建Java线程的两种方法
- Java 线程的基本概念 创建方法 和 基本操作
- Java:使用匿名内部类在方法内部定义并启动线程