如果线程中断,则finally块的行为

时间:2014-04-01 09:36:09

标签: java multithreading

我正在学习java中的线程。根据{{​​3}}:

  

注意:如果在执行try或catch代码时JVM退出,则finally块可能无法执行。 同样,如果执行try或catch代码的线程被中断或终止,则即使整个应用程序仍在继续,finally块也可能无法执行。

所以我试着在try catch块中断一个线程,并检查finally是否在下面的类中执行。但是根据程序的输出,最后执行块。有人可以解释发生了什么吗?

package com.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


 public class TestLock{
     public static void main(String[] args) throws InterruptedException {
          MyThread lockT= new MyThread();
         Thread t= new Thread(lockT); 
         t.setName("TempThread1"); 
         t.start();
         Thread.sleep(1000); 
         t.interrupt();
    }
 }

 class MyThread implements Runnable {
        Lock lock;
        public MyThread() {
            lock= new ReentrantLock();
        }
        @Override
        public void run() { 
            try {
                if(lock.tryLock()){
                         Thread.sleep(5000);
                     while (!Thread.currentThread().isInterrupted()) { 
                            System.out.println("My thread name is   "+ Thread.currentThread().getName());        
                     }                  
                }
            } catch (Exception e) {
                e.printStackTrace();                
            }finally{
                System.out.println("finally ");
                lock.unlock();
            }           

        }


    }

4 个答案:

答案 0 :(得分:4)

此处的规则是:may not execute并不代表it will not execute

所以基本上规则是说:不要依赖finally块将被执行,我们不提供这样的保证。

答案 1 :(得分:1)

我知道它是一个老线程,但是我想提出一个情况,即线程被中断并且最终不会执行:这是示例代码:

public class Test {
public static void main(String[] args) {
    Test test = new Test();
    test.LockWork();
}public void LockWork() {
    WithLock withLock = new WithLock();
    Thread t1 = new Thread(() -> {
        withLock.produce();
    });
    Thread t2 = new Thread(() -> {
        withLock.consume();
    }); 
    ExecutorService service= Executors.newCachedThreadPool(new WithLockThreadFactory());
    Future f1=service.submit(t1);
    Future f2=service.submit(t2);
    //f1.cancel(true);
    try {
        System.out.println("-------------------------------------sleeping now-------------------------------------");
        Thread.sleep(3000);
        System.out.println("-------------------------------------Intereputing Producer-------------------------------------");
        f1.cancel(true);
        service.shutdown();
        Thread.sleep(1000);
        System.out.println("is Producer done: "+f1.isDone());
        service.awaitTermination(1, TimeUnit.DAYS);
        System.out.println("is Consumer done: "+f2.isDone());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("Ending Program");
}

现在有我的线程工厂:

public class WithLockThreadFactory implements ThreadFactory {
private int counter;

public WithLockThreadFactory() {
    this.counter = 1;
}

@Override
public Thread newThread(Runnable r) {
    Thread t = new Thread(r, "WithLockThreadFactoryThread " + counter);
    counter++;
    return t;
}

现在WithLock Class:

public class WithLock {
ReentrantLock lock = new ReentrantLock(true);
LinkedList<Integer> linkedList = new LinkedList<>();
Condition isEmpty = lock.newCondition();
Condition isFull = lock.newCondition();
int limit = 10;
volatile int interruptCounter = 0;

public void produce() {
    System.out.println("WithLock.produce() Name: " + Thread.currentThread().getName());
    try {
        int value = 1;
        while (true) {
            lock.lockInterruptibly();
            if (limit == linkedList.size()) {
                System.out.println("acquiring lock in produce");
                isEmpty.await(3000, TimeUnit.MILLISECONDS);
            }
            linkedList.add(value % limit);
            System.out.println("value added to list: " + value % limit);
            value++;
            isFull.signal();
            System.out.println("notifiedy lock in produce");
            lock.unlock();
            Thread.sleep(1000);
        }
    } catch (InterruptedException e) {
        System.out.println("I was interupted Producer");
        interruptCounter++;
        System.out.println("interruptCounter value :" + interruptCounter);
    } finally {
        lock.unlock();
        System.out.println("Finally Unlocked Producuer");
    }
    System.out.println("Ending things now: Producer");
}

public void consume() {
    System.out.println("WithLock.consume() Name: " + Thread.currentThread().getName());
    try {
        while (true) {
            lock.lockInterruptibly();
            // no use as poll doesn't throw an exception if the queue is
            // empty
            if (linkedList.size() == 0) {
                System.out.println("acquiring lock in consume");
                isFull.await(3000, TimeUnit.MILLISECONDS);
                if (interruptCounter > 2) {
                    break;
                }
            }
            System.out.println("removing element from queue: " + linkedList.poll());
            isEmpty.signal();
            System.out.println("notifiedy lock in consume");
            lock.unlock();
            Thread.sleep(1000);
            if (interruptCounter != 0) {
                interruptCounter++;
            }
        }
    } catch (InterruptedException e) {
        System.out.println("I was Interupted Consumer");
    } finally {
        lock.unlock();
        System.out.println("Finally Unlocked Consumer");
    }
    System.out.println("Ending things now: Consume");
}

}

这是控制台中的输出:

    -------------------------------------sleeping now-------------------------------------
WithLock.produce() Name: WithLockThreadFactoryThread 1
WithLock.consume() Name: WithLockThreadFactoryThread 2
value added to list: 1
notifiedy lock in produce
removing element from queue: 1
notifiedy lock in consume
acquiring lock in consume
value added to list: 2
notifiedy lock in produce
removing element from queue: 2
notifiedy lock in consume
acquiring lock in consume
value added to list: 3
notifiedy lock in produce
removing element from queue: 3
notifiedy lock in consume
-------------------------------------Intereputing Producer-------------------------------------
I was interupted Producer
interruptCounter value :1
acquiring lock in consume
is Producer done: true
removing element from queue: null
notifiedy lock in consume
acquiring lock in consume
Finally Unlocked Consumer
Ending things now: Consume
is Consumer done: true
Ending Program

这是我觉得有趣并希望分享的内容。我在JAVA8中尝试过它。

答案 2 :(得分:0)

  

如果JVM退出......

尝试System.exit()来电...

答案 3 :(得分:0)

首先,Oracle的教程是描述性而不是规范。您的引用绝不应被视为行为规范。

在执行finally块时,线程可能被中断,在这种情况下,所述finally块可能确实无法完成。但是,这完全在您的控制之下,您总是可以编写一个finally这样不容易发生这种情况。

请放心,finally阻止不会因InterruptedException阻止try阻止stop()阻止而被跳过。

但是,如果线程重复finally,则确保执行{{1}}块将更加困难。