java 线程中断

java中断是一种中断机制 如果我们写的线程没有对中断请求进行响应那么线程是无法被中断的。(这里说的是线程代码是指在子线程中运行的所有方法代码。当然第一个方法就是Thread的run方法)

示例代码:

public class ThreadInterruptTest {

    //任务的阻塞队列
    BlockingQueue<Runnable> blockingQueue;

    public static void main(String[] args) {
	ThreadInterruptTest test = new ThreadInterruptTest();
	test.init();
    }

    /**
     *<p>TODO(概括性描述)</p><br/>
     *<p>TODO(详细描述)</p>
     * @since 2.6
     * @author liulp
     */
    private void init() {
	// TODO Auto-generated method stub

	//初始化阻塞队列
	blockingQueue = new ArrayBlockingQueue<Runnable>(20);

	Thread t = new Thread() {
	    @Override
	    public void run() {
		// TODO Auto-generated method stub
		super.run();

		//从队列中取任务 然后执行 直到执行完任务
		while (true) {

		    MyRunnable run = (MyRunnable) blockingQueue.poll();
		    if (run != null) {
			System.out.println("task "+run.i+" start");

			//执行任务
			run.run();

		    } else {
			break;
		    }
		}
	    }
	};
	
	//添加10个任务
	for (int i = 1; i <= 10; i++) {
	    try {
		blockingQueue.put(new MyRunnable(i));
	    } catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	}
	//启动线程
	t.start();

	//中断线程
	t.interrupt();
	
	//继续添加任务
	blockingQueue.add(new MyRunnable(11));

    }

    class MyRunnable implements Runnable {

	int i;

	/**
	 * 
	 */
	public MyRunnable(int i) {
	    // TODO Auto-generated constructor stub
	    this.i = i;
	}

	@Override
	public void run() {
	    int m = 0;
	    int a = 0;
	    
	    //消耗CP时间
	    for (; m < Integer.MAX_VALUE; m++) {
		a++;
	    }

	    System.out.println("Task " + i + " end");
	}
    }

}

运行结果:

task 1 start
Task 1 end
task 2 start
Task 2 end
task 3 start
Task 3 end
task 4 start
Task 4 end
task 5 start
Task 5 end
task 6 start
Task 6 end
task 7 start
Task 7 end
task 8 start
Task 8 end
task 9 start
Task 9 end
task 10 start
Task 10 end
task 11 start
Task 11 end

可以看到 虽然我们调用了线程的中断但是所有的任务都执行完毕了,甚至我们在调用中断后添加的任务也执行了。

那么我们应该怎么样中断任务呢?

我们知道java的线程中断时一种写作机制,并不是调用线程的中断方法 就可以中断线程,而是需要任务的执行者来响应中断才可以。

我们稍微修改下MyRunnable的run方法来响应中断。

public void run() {
	    
	    //如果有中断请求
	    if(Thread.interrupted()){
		//直接reutrn掉
		return;
	    }
	    
	    int m = 0;
	    int a = 0;
	    
	    //消耗CP时间
	    for (; m < Integer.MAX_VALUE; m++) {
		a++;
	    }

	    System.out.println("Task " + i + " end");
	}

运行结果如下:

task 1 start
task 2 start
Task 2 end
task 3 start
Task 3 end
task 4 start
Task 4 end
task 5 start
Task 5 end
task 6 start
Task 6 end
task 7 start
Task 7 end
task 8 start
Task 8 end
task 9 start
Task 9 end
task 10 start
Task 10 end
task 11 start
Task 11 end
哦看起来好像没有什么变化,所有的任务都打印了,但是仔细看你会发现少了一句
task 1 end
这说明task 1的run方法没有执行完 而是return了。

我们通过在run方法中检查中断状态中断了task 1的执行,但是其他的任务并没有被中断,这是因为调用thread.interrupted()会恢复状态中断,在线程中第二次调用

interrupted() 就返回false了,如果我们想中断所有的任务怎么办呢?那只有想办法让线程完全终止,我们可以通过跑车一个Error 或是RuntimeExcepton终止线程的

执行,我们再次修改 MyRunnable的run方法:

@Override
	public void run() {
	    
	    //如果有中断请求
	    if(Thread.interrupted()){
//		Error e =new Error("die");
		RuntimeException e = new RuntimeException("die");
		throw(e);
	    }
	    
	    int m = 0;
	    int a = 0;
	    
	    //消耗CP时间
	    for (; m < Integer.MAX_VALUE; m++) {
		a++;
	    }

	    System.out.println("Task " + i + " end");
	}

运行结果:

task 1 start
Exception in thread "Thread-0" java.lang.RuntimeException: die
    at com.popo.test.thread.ThreadInterruptTest$MyRunnable.run(ThreadInterruptTest.java:103)
    at com.popo.test.thread.ThreadInterruptTest$1.run(ThreadInterruptTest.java:56)

线程完全被终止了,不过如果我们在Thread.run()方法中捕获RuntimeException线程也是不会被终止的,有兴趣的可以实现下。

当然我们如果在执行任务队列是不应该中断其他任务的执行的,除非调用者有显示的调用(比如Executes.shutDownNow()方法 就是终止所有未完成的任务)

最后加上一段 Thread.interrupt()方法的注释

Posts an interrupt request to this Thread. The behavior depends on the state of this Thread:

也就是说在上边两种阻塞情况下 线程会被唤醒 并抛出异常,我们可以通过捕获异常来响应中断。

第三种情况会设置中断状态 并且selector马上返回但是不会收到异常。这种异常处理应该需要程序员自己去检查中断状态来响应中断。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值