java中线程的取消

Java中没有一种安全的抢占式方法来停止线程,只有一种协作式的机制。

大致分为两种协作式机制:1.设置某个”已请求取消“的标志,线程任务定期查看该标志。如果取消标志设置为true,则结束任务

2.调用线程的interrupt()能中断目标线程,通过Thread.currentThread().isInterrupted()方法来查询,也可以通过大多数可阻塞的库函数(如Thread.sleep和Object.wait)来抛出InterruptedException异常,在异常中退出线程。

第一种中断方式的实现代码:

public class PrimeGenerator implements Runnable{

private final List<BigInteger> primes=new ArrayList<BigInteger>();

private  volatile boolean cancelled;   //需要将cancelled设置为volatile变量,确保当一个线程修改后,对其他线程是可见的

@Override

public void run() {

// TODO Auto-generated method stub

BigInteger p=BigInteger.ONE;

while(!cancelled){

p=p.nextProbablePrime();

synchronized(this){

primes.add(p);

}

}

}

public void cancel(){

cancelled=true;

}

}

这种中断方式在任务调度一个阻塞方法时,例如BlockingQueue.put方法时,会使线程一直阻塞,任务可能永远不会检查取消标志,因此会出现取消失败的情况

第二种中断方式的实现代码:

public class PrimeProducer implements Runnable{

private final BlockingQueue<BigInteger> queue;

PrimeProducer(BlockingQueue<BigInteger> queue){

this.queue=queue;

}

public void run() {

// TODO Auto-generated method stub

try {

BigInteger p = BigInteger.ONE;

while (!Thread.currentThread().isInterrupted()) {

queue.put(p = p.nextProbablePrime());

// Thread.currentThread().sleep(10);

System.out.println(queue.size());

}

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

System.out.println("中断了,请处理中断");

}

}

public static void main(String[] args){

BlockingQueue<BigInteger> queue=new ArrayBlockingQueue<BigInteger>(999999);

Thread th1=new Thread(new PrimeProducer(queue));

th1.start();

try {

Thread.currentThread().sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

th1.interrupt();

}

}

这种方式使用中断机制才中断,上面代码中有两个位置可以检验出中断:Thread.currentThread().isInterrupted()方法和阻塞方法put的调用。

注意第二种机制的run方法还能写成下面模式,将中断异常处理放在while循环体内,但是必须要在异常处理catch语句块加上Thread.currentThread().interrupt()这句来重置中断状态,否则有可能无法终止任务。这是由于阻塞库方法在检查到线程中断时抛出InterruptException异常前,会清除中断状态。使得while在判断Thread.currentThread().isInterrupted() 时会返回false,则线程不会退出,因此需要在异常处理块重置中断。

public void run() {

// TODO Auto-generated method stub

BigInteger p=BigInteger.ONE;

while(!Thread.currentThread().isInterrupted()){

try {

queue.put(p=p.nextProbablePrime());

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

System.out.println("中断了,请处理中断");

Thread.currentThread().interrupt(); ///捕获InterruptedException后恢复中断状态

}

//Thread.currentThread().sleep(10);

System.out.println(queue.size());

}

}

参考资料

《Java Concurrency in Practice》Brian Goetz等著

时间: 2024-10-10 15:51:34

java中线程的取消的相关文章

Java中线程封闭之ThreadLocal

在访问共享数据时通常使用同步.若不使用同步则可以将对象封闭在一个线程中达到线程安全的目的,该方法称为线程封闭(Thread Confinement).其中实现线程封闭中规范的方法是使用ThreadLocal类.线程封闭技术一种常用的使用场景是在JDBC Connection对象. public class ConnectionHelper{private final static String URL = "";private final static ThreadLocal<C

多线程(三) java中线程的简单使用

============================================= 原文链接:多线程(三) java中线程的简单使用 转载请注明出处! ============================================= java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依旧是实现了Runnabel接口.考虑到java的

java中线程存活和线程执行的问题!

1 /* 2 下面的程序会出现下面的情况,当Thread-0, Thread-1, Thread-2都被wait的时候,可能会同时苏醒 3 Thread-0 put 4 Thread-1 put 5 Thread-2 put 6 Thread-3 get//在此处,Thread-3拿到锁之后,将所有的等待的线程唤醒,才有了下面的输出 7 Thread-2 put 8 Thread-1 put 9 Thread-0 put 10 */ 11 12 13 虽然多个线程会同时苏醒,但是只有一个能获得c

Java中线程同步的理解 - 其实应该叫做Java线程排队

Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等. 当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程"同步"机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团. 同步这个词是从英文synchronize(使同时发生)翻译过来的.我也不明白为什么

线程的生命周期 - 理解Java中线程的状态

刚刚开始学cocos2-x,仅仅是按照教程把已经安了一般Android的开发环境的eclipse重新升级到安装好cdt和ndk就花了我几十小时,差点都要放弃了. 参考博客 D:\cocos2d-x\cocos2d-x-2.2.3\cocos2dx\platform\third_party\android\prebuilt 说说大概的过程: 下载ndk插件,ndk包,cdt插件.最开始我按照书上的下载了cocos2d-x 2.0.1,希望跟书上统一起来,这样以后学习的时候可以参考书上的也不会遇到太

Java中线程顺序执行

现有线程threadone.threadtwo和threadthree,想要的运行顺序为threadone->threadtwo->threadthree,应该如何处理?这里需要用到一个简单的线程方法join(). join()方法的说明:join方法挂起当前调用线程,直到被调用线程完成后在继续执行(join() method suspends the execution of the calling thread until the object called finishes its ex

java中线程的状态

java中线程有哪些状态? Thread类有一个内部的枚举,State 1.NEW 创建了一个Thread对象,还没有执行start之前,状态为NEW 2.RUNNABLE 调用了Thread的start()方法,状态变为 RUNNABLE 3.BLOCKED 正在等待获取锁,状态为BLOCKED.例如synchronized 4.WAITING 调用 Object.wait() 或 join() 方法后,线程进入WAITING状态.调用wait()方法需要通过notify()或notifyAl

Java中线程的实现:

Java中线程的实现: 一.线程简介: 实现的两种方式为: 1.Thread类 2.Runnable接口 都在java.lang中 都有共通的方法:public void run() 二.线程常用方法 线程启动:start() 线程睡眠:sleep() 线程抢占:join() 线程让步:yield() 三.线程实例 实例一:Thread类实现 class Xc extends Thread   //创建线程所需要继承的类 { public void run()            //run方

Java中线程(Thread)知识概括

Java中线程(Thread)知识概括 进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行. 一个进程中至少有一个线程. 例如:Java VM 启动的时候会有一个进程java.exe.该进程中至少一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中.该线程称之为主线程.jvm启动不止一个线程,还有负责垃圾回收机制等线程. 如何在自定义的代码中,自定义一个线程呢