【Java 多线程并发】 Runnable

Metadata

title: 【Java 多线程并发】 Runnable
date: 2023-07-03 10:17
tags:
  - 行动阶段/完成
  - 主题场景/程序
  - 笔记空间/KnowladgeSpace/ProgramSpace/BasicsSpace
  - 细化主题/Java
categories:
  - Java
keywords:
  - Java
description: Runnable接口是Java中用于表示可执行任务的接口,通过实现该接口并实现run()方法,可以在单独的线程中执行代码逻辑。它是多线程编程中常用的一种方式,可以提高代码的灵活性和可维护性。

概述

Runnable是Java中的一个接口,位于java.lang包中。
它是一个函数式接口,用于表示可以被线程执行的任务。

【Java 多线程并发】 Runnable

Runnable是Java中的一个接口,位于java.lang包中。它是一个函数式接口,用于表示可以被线程执行的任务。实现了Runnable接口的类可以在单独的线程中执行代码逻辑,而不需要继承Thread类。

Runnable接口只有一个抽象方法run(),该方法没有参数和返回值。当一个线程启动时,会调用Runnable接口实现类的run()方法,在独立的执行线程中执行具体的任务逻辑。

使用Runnable接口的优势在于,代码逻辑与线程的执行逻辑分离,提高了代码的可维护性和复用性。此外,使用Runnable接口还可以避免单继承的限制,因为一个类可以同时实现多个接口。

总之,Runnable接口是Java中用于表示可执行任务的接口,通过实现该接口并实现run()方法,可以在单独的线程中执行代码逻辑。它是多线程编程中常用的一种方式,可以提高代码的灵活性和可维护性。

Runnable 源码

简化版

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

中文注释版

/**
 * <code>Runnable</code>接口应该被任何希望被线程执行的类实现。该类必须定义一个无参数的名为<code>run</code>的方法。
 * <p>
 * 该接口旨在为希望在活动状态下执行代码的对象提供一个常见的协议。例如,<code>Runnable</code>由<code>Thread</code>类实现。
 * 活动状态意味着线程已经启动但尚未停止。
 * <p>
 * 此外,<code>Runnable</code>提供了一种方式,使得一个类在不继承<code>Thread</code>的情况下也可以保持活动状态。
 * 实现<code>Runnable</code>的类可以通过实例化一个<code>Thread</code>实例并将自身作为目标传递进去来运行。
 * 在大多数情况下,如果只打算重写<code>run()</code>方法而不是其他<code>Thread</code>方法,应该使用<code>Runnable</code>接口。
 * 这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应该对类进行子类化。
 *
 * @author  Arthur van Hoff
 * @see     java.lang.Thread
 * @see     java.util.concurrent.Callable
 * @since   JDK1.0
 */
@FunctionalInterface
public interface Runnable {
    /**
     * 当使用实现<code>Runnable</code>接口的对象创建一个线程时,启动线程会导致该对象的<code>run</code>方法在单独的执行线程中被调用。
     * <p>
     * 方法<code>run</code>的一般约定是它可以执行任何操作。
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

使用说明及注意点

根据上述代码的注释,可以总结出以下关于Runnable接口的使用说明和注意点:

  1. Runnable接口应该被希望在单独的线程中执行的类实现。
  2. 实现Runnable接口的类必须定义一个无参数的run()方法,该方法将在单独的执行线程中被调用。
  3. Runnable接口为希望在活动状态下执行代码的对象提供了一个常见的协议。
  4. 通过实例化一个Thread对象并将实现了Runnable接口的对象作为目标传递进去,可以使实现了Runnable接口的类在不继承Thread类的情况下保持活动状态。
  5. 在大多数情况下,如果只打算重写run()方法而不是其他Thread方法,应该使用Runnable接口。
  6. 子类化类应该是有意修改或增强类的基本行为才进行的,所以不应该轻易对类进行子类化。
  7. Runnable接口是一个函数式接口,可以使用lambda表达式或方法引用来实现。
  8. run()方法的一般约定是可以执行任何操作,根据具体需求编写逻辑。

总之,通过实现Runnable接口,可以将代码逻辑与线程分离,提高代码的复用性和可维护性。同时,需要注意在run()方法中编写线程执行的具体逻辑,并确保线程安全性。

Runnable 异常处理

当Runnable接口的实现类中的run()方法抛出异常时,可以通过以下几种方式来处理异常:

直接捕获

在run()方法内部捕获异常:在run()方法的实现中使用try-catch语句来捕获异常并进行处理。这种方式可以在run()方法内部处理异常,但需要确保异常不会被抛出到run()方法之外。

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        try {
            // 执行可能会抛出异常的代码
        } catch (Exception e) {
            // 处理异常
        }
    }
}

声明抛出异常

在run()方法上使用throws关键字声明异常:在run()方法的声明中使用throws关键字声明可能抛出的异常。这样做可以将异常传递给调用方处理。

public class MyRunnable implements Runnable {
    @Override
    public void run() throws Exception {
        // 执行可能会抛出异常的代码
    }
}

Thread.UncaughtExceptionHandler

在run()方法内部使用UncaughtExceptionHandler处理未捕获的异常:可以通过实现Thread.UncaughtExceptionHandler接口,并将其设置为线程的未捕获异常处理程序来处理未捕获的异常。这样做可以在异常未被捕获时进行处理,例如记录日志或进行其他操作。

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 执行可能会抛出异常的代码
    }
}

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                // 处理未捕获的异常
            }
        });
        thread.start();
    }
}

根据具体的需求和场景,选择适合的异常处理方式。无论使用哪种方式,都应该确保异常能够得到适当的处理,以避免程序出现不可预料的错误或异常终止。