Java 中创建线程几种方式

目录

概述

[一. 继承Thread类](#一. 继承Thread类)

[1. 特点](#1. 特点)

[2. 注意事项](#2. 注意事项)

[3. 代码示例](#3. 代码示例)

[二. 实现Runnable接口](#二. 实现Runnable接口)

[1. 特点](#1. 特点)

[2. 注意事项](#2. 注意事项)

[3. 代码示例](#3. 代码示例)

[三. 实现Callable接口](#三. 实现Callable接口)

[1. 特点](#1. 特点)

[2. 注意事项](#2. 注意事项)

[3. 代码示例](#3. 代码示例)


概述

在Java中,线程(Thread)是程序执行的最小单元,它允许程序在同一时间执行多个任务。Java中的线程可以由Thread类创建,也可以通过实现Runnable接口或Callable接口创建。

java中线程几种状态:

  1. 新建(New) : 线程对象已经被创建,但还没有调用start()方法。

  2. 可运行(Runnable) : 线程已经调用了start()方法,但还没有获得CPU时间片执行。可运行状态包括了操作系统线程的就绪(Ready)和运行(Running)状态。

  3. 阻塞(Blocked): 线程因为等待监视器锁而被阻塞,无法继续执行。

  4. 等待(Waiting) : 线程通过调用wait()、join()、LockSupport.park()等方法进入等待状态,需要其他线程通知或中断后才可能继续执行。

  5. 超时等待(Timed Waiting) : 线程通过调用带有超时参数的sleep()、wait()、join()、LockSupport.parkNanos()、LockSupport.parkUntil()等方法进入超时等待状态,超时后会自动唤醒。

  6. 终止(Terminated) : 线程的run()方法执行结束,或者因异常退出了run()方法。

线程的状态枚举类 State

一. 继承Thread类

通过继承Thread类并重写run方法来创建线程,本质上继承Thread类实现线程的方式也是通过实现 Runnable 接口,

1. 特点

  • 简单性:实现线程的代码简单直观。
  • 局限性 :由于Java的单继承特性,如果一个类已经继承了其他类,就不能再继承Thread类。

2. 注意事项

  • 不要调用Thread类的run方法 :应该重写run方法,而不是直接调用它。
  • 使用start方法启动线程 :start方法会创建一个新的线程,并调用run方法。
  • 线程安全:如果线程之间需要共享数据,需要考虑线程安全问题。

3. 代码示例

java 复制代码
package com.demo.thread;

/**
 * 文件名:ThreadDemo
 * 创建者:
 * 创建时间:2024-09-22
 * 描述: 通过继承 Thread 类并重写run方法来创建线程
 */
public class ThreadDemo extends Thread{
    @Override
    public void run(){
        System.out.println(Thread.currentThread().getName()+"-执行run方法");
    }
}

/**
 * 测试类
 */
class MainThread{
    public static void main(String[] args) {
        //1.第一种方式创建线程
        Thread thread = new Thread(new ThreadDemo(),"线程1");
        thread.start(); //启动线程

        //2.第二种方式创建线程
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"-执行run方法");
            }
        },"线程2");
        thread2.start(); //启动线程
    }
}

二. 实现Runnable接口

实现 Runnable 接口是Java中创建线程的另一种常见方式,这种方式更加灵活,因为它允许类继承其他类的同时实现线程功能。Runnable 接口定义了一个 run 方法,这是线程执行的入口点。

1. 特点

  • 灵活性 :实现 Runnable 接口允许类继承其他类,同时实现多线程功能。
  • 线程安全 :如果多个线程共享同一个 Runnable 实例,需要考虑线程安全问题。

2. 注意事项

  • 不要在 run 方法中调用 Thread.currentThread().stop():这是不推荐的做法,因为它可能会导致程序处于不确定状态。
  • 异常处理 :在 run 方法中妥善处理异常,避免线程意外终止。
  • 资源清理:如果线程使用了一些资源(如文件句柄、数据库连接等),确保在线程结束时释放这些资源。

3. 代码示例

java 复制代码
package com.demo.thread;

/**
 * 文件名:RunnableDemo
 * 创建者:
 * 创建时间:2024-09-22
 * 描述:实现 Runnable接口创建线程
 */
public class RunnableDemo implements Runnable{
    public void run() {
        System.out.println(Thread.currentThread().getName()+"-"+"执行run方法");
    }
}

/**
 * 测试类
 */
class MainDemo{
    public static void main(String[] args) {
        //1.第一种创建线程执行
        Thread thread = new Thread(new RunnableDemo(),"线程1");
        thread.start(); // 启动线程

        //2.第二种创建线程执行
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"-执行run方法");
            }
        },"线程2");
        thread2.start(); // 启动线程

    }
}

三. 实现Callable接口

当我们需要创建一个可以返回结果的线程时,就可以使用实现了Callable接口的方式。Callable接口是在Java 5中引入的,它允许线程执行一个任务并返回一个结果,与Runnable接口相比,Callable接口的call()方法可以返回结果并抛出异常。

Callable 接口与 Runnable 接口类似,但它可以返回一个结果并且能抛出异常。Callable 通常与 FutureTask 一起使用,后者实现了 Runnable 接口,并且包装了 Callable 对象。

1. 特点

  • 返回结果 :Callable 任务可以返回一个结果,可以通过 FutureTask.get() 方法获取。
  • 抛出异常 :Callable 任务可以抛出异常,可以通过 FutureTask.get() 方法捕获。

2. 注意事项

  • 异常处理 :在 call 方法中抛出的异常可以通过 FutureTask.get() 方法的调用者捕获。
  • 线程安全 :如果 Callable 任务需要访问共享资源,需要考虑线程安全问题。

3. 代码示例

使用步骤:

  1. 创建一个实现 Callable 接口的类。
  2. 实现 Callable 接口的 call 方法,该方法是线程执行的入口点。
  3. 创建 Callable 实例。
  4. 将 Callable 实例传递给 FutureTask 的构造器。
  5. 将 FutureTask 对象传递给 Thread 类的构造器。
  6. 创建 Thread 对象。
  7. 调用 Thread 对象的 start 方法来启动线程。
  1. 简单使用

    java 复制代码
    package com.demo.thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    /**
     * 文件名:CallableDemo
     * 创建者:
     * 创建时间:2024-09-22
     * 描述:通过 Callable 接口实现线程创建
     */
    public class CallableDemo implements Callable<String> {
        @Override
        public String call() throws Exception {
            return "测试";
        }
    }
    
    /**
     * 测试类
     */
    class MainCallable{
        public static void main(String[] args){
            //1.创建对象
            CallableDemo demo = new CallableDemo();
            FutureTask<String> futureTask = new FutureTask<>(demo);
            //2.创建线程
            Thread thread = new Thread(futureTask);
            thread.start();
            //3.获取返回结果
            String res;
            try {
                res = futureTask.get();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
            System.out.println("获取线程返回结果:"+res);
        }
    }
  2. 通过线程池使用

    java 复制代码
    package com.demo.thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * 文件名:Main
     * 创建者:
     * 创建时间:2024-09-22
     * 描述:
     */
    public class Main {
        public static void main(String[] args) {
            //1.创建一个线程池
            ExecutorService executorService = Executors.newSingleThreadExecutor();
            //2.创建Callable任务
            Callable<String> callableTask = () -> {
                Thread.sleep(2000); // 模拟长时间运行的任务
                return "测试";
            };
            //3.提交Callable任务并获取Future对象
            Future<String> future = executorService.submit(callableTask);
            try {
                //3.获取异步任务的执行结果
                String result = future.get(); //此方法会阻塞,直到任务执行完成
                System.out.println("任务执行结果: " + result);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //4.关闭线程池
                executorService.shutdown();
            }
        }
    }
相关推荐
小羊没烦恼!3 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里3 天前
java中的继承和多态的区别
java
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕3 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码3 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖3 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时3 天前
01-06-A-JVM排查实战详解
java·jvm
vipxieliang3 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
ba_pi3 天前
mysql 查询所有表名并授权
java
ProcessOn官方账号3 天前
java函数式编程--入门基础
java·编程·函数式编程