在主线程中处理InterruptedException

时间:2017-04-20 14:39:35

标签: java multithreading

我想知道在主线程中处理InterruptedException的正确方法是什么。当主线程被中断时?

我看到join()方法抛出InterruptedException,但我想知道如何清理辅助线程以便正常终止。

以下是示例程序:

[main] starting the thread
[main] interrupting the secondary thread
[thread] exiting...
[main] exiting

此代码将打印以下输出:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread mainThread = Thread.currentThread();
        Thread t = new Thread() {
            public void run() {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        break;
                    }
                }
                System.out.println("[thread] interrupting the main thread...");
                mainThread.interrupt();
                System.out.println("[thread] exiting...");
            }
        };

        System.out.println("[main] starting the thread");
        t.start();
        System.out.println("[main] interrupting the secondary thread");
        t.interrupt();

        try {
            t.join();
        } catch (InterruptedException e) {
            System.out.println("[main] InterruptedException indeed happened");
            Thread.currentThread().interrupt();
            throw e;
        }
        System.out.println("[main] exiting");
    }
}

我发现互联网上的某些文章(例如此http://www.yegor256.com/2015/10/20/interrupted-exception.html)建议将中断标志设置为true并抛出RuntimeException。我不知道这会如何缓解这种情况(在退出之前清理剩余的线程)。

感谢。

编辑:代码剪切我在评论中提到

public void cancelNotification()
    {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(AcceptUserRequest.this);
        builder.setSmallIcon(R.mipmap.lo);
        builder.setLargeIcon(BitmapFactory.decodeResource(this.getApplicationContext().getResources(),
                R.mipmap.peoplehelperlogo));

    builder.setContentTitle("PEOPLE HELPER");
    builder.setContentText("Accepted request has been cancelled");
    builder.setAutoCancel(true);

    Intent intent = new Intent(AcceptUserRequest.this, BroadcastFragment.class); //creates an explicit intent
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(AcceptUserRequest.this);
    stackBuilder.addParentStack(AcceptUserRequest.this); //adds the intent
    stackBuilder.addNextIntent(intent);  //put the intent to the top of the stack
    PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); //(id, flag) //creates a pending intent
    builder.setContentIntent(pendingIntent); //adds the PendingIntent to the builder
    NotificationManager notificationManager = (NotificationManager) AcceptUserRequest.this.getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, builder.build());
}

1 个答案:

答案 0 :(得分:1)

在您的示例中,没有任何内容会中断主线程,处理从辅助线程上的调用加入引发的InterruptedException的代码都不会被执行。所以这并不重要。设置中断标志的目的是让在该线程中执行的其他事情知道中断,这样一切都可以退出它正在做的事情,这不是一个问题。

您可以将main方法包装在try-catch块中,以记录它捕获的任何内容。要确保记录所有异常,这是正常的做法。

您的代码在辅助线程上调用interrupt。只要编写该线程以通过清理和退出来响应中断,就不会再做任何事情了。

请勿使用Thread.interrupted(),请使用Thread.currentThread().isInterrupted()interrupted方法将中断标志清除为副作用。

捕获InterruptedException并抛出RuntimeException与编写java.util.concurrent类的方式不一致。让InterruptedException被抛出比将它包装在未经检查的异常中更为惯用。

示例代码不能被信号中断,您必须自己通过编写自己的信号处理程序来实现该功能。