1.停止一个线程什么方法?
interceptor:中断线程.不能用stop()方法,非常不安全
在介绍线程池关闭之前,先介绍下Thread的interrupt。
在程序中,我们是不能随便中断一个线程的,因为这是极其不安全的操作,我们无法知道这个线程正运行在什么状态,它可能持有某把锁,强行中断可能导致锁不能释放的问题;或者线程可能在操作数据库,强行中断导致数据不一致混乱的问题。正因此,JAVA里将Thread的stop方法设置为过时,以禁止大家使用。
一个线程什么时候可以退出呢?当然只有线程自己才能知道。
所以我们这里要说的Thread的interrrupt方法,本质不是用来中断一个线程。是将线程设置一个中断状态。
当我们调用线程的interrupt方法,它有两个作用:
1、如果此线程处于WAITING状态,并抛出InterruptedException异常,线程就可以通过捕获InterruptedException来做一定的处理,然后让线程退出。而处于BLOCKED状态的线程不会抛出异常.关闭不了.
2、如果此线程正处于RANNABLE状态,则线程不受任何影响,继续运行,仅仅是线程的中断标记被设置为true。所以线程要在适当的位置通过调用isInterrupted方法来查看自己是否被中断,并做退出操作。
举例:LeedCode多线程1195题.
链接:LeedCode多线程交替打印字符串
在如下题目中,其他线程(打印字母的线程)在调用acquire()方法后,如果获取不到信号量就会进入WAITING状态,并且永远在等待,线程不会结束,所以在主线程(打印普通数字的线程)执行完条件后,需要将等待的线程一一进行中断,然后捕获异常,程序正常退出.
class FizzBuzz {
private int n;
public FizzBuzz(int n) {
this.n = n;
}
Semaphore fizzSemaphore=new Semaphore(0);
Semaphore buzzSemaphore=new Semaphore(0);
Semaphore fizzbuzzSemaphore=new Semaphore(0);
BlockingQueue<Thread> threadQueue = new LinkedBlockingQueue<>(1);
ArrayList<Thread> threadList=new ArrayList<>(3);
// printFizz.run() outputs "fizz".
public void fizz(Runnable printFizz) throws InterruptedException {
threadList.add(Thread.currentThread());
for(;;){
try{
fizzSemaphore.acquire();
}catch(InterruptedException e){
break;
}
printFizz.run();
LockSupport.unpark(threadQueue.poll());
}
}
// printBuzz.run() outputs "buzz".
public void buzz(Runnable printBuzz) throws InterruptedException {
threadList.add(Thread.currentThread());
for(;;){
try{
buzzSemaphore.acquire();
}catch(InterruptedException e){
break;
}
printBuzz.run();
LockSupport.unpark(threadQueue.poll());
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
threadList.add(Thread.currentThread());
for(;;){
try{
fizzbuzzSemaphore.acquire();
}catch(InterruptedException e){
break;
}
printFizzBuzz.run();
LockSupport.unpark(threadQueue.poll());
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void number(IntConsumer printNumber) throws InterruptedException {
for(int i=1;i<=n;i++){
if(i % 3!=0 && i % 5!=0){
printNumber.accept(i);
}else if(i % 3==0 && i % 5 !=0){
threadQueue.put(Thread.currentThread());
fizzSemaphore.release();
LockSupport.park();
}else if(i % 3!=0 && i % 5 ==0){
threadQueue.put(Thread.currentThread());
buzzSemaphore.release();
LockSupport.park();
}else{
threadQueue.put(Thread.currentThread());
fizzbuzzSemaphore.release();
LockSupport.park();
}
}
//将其他在WAITING状态的线程强制结束
for(int i=0;i<threadList.size();i++){
Thread curThread=threadList.get(i);
curThread.interrupt();
}
}
}
2.关停线程池用什么方法?,那正在运行的线程怎么办?
关闭线程池有两个方法:
showdown:按顺序关闭已提交任务的线程,同时不允许提交新的任务.会把所有已经提交的任务执行完再关闭.推荐使用该方法.
showdownNow:尝试立即关闭所有的线程,一旦执行完当前任务就会被关闭,而新提交的任务不会被执行.
其内部调用interrupt方法.但是不保证能够关闭所有线程,比如说不能对intertupt做出正确响应的线程.对于那些sleep的线程会抛出中断异常.整个程序终止.处于block状态的线程不会抛出异常.关闭不了.同时移除正在等待的任务.