java开启线程的四种方法

简介: 这篇文章介绍了Java中开启线程的四种方法,包括继承Thread类、实现Runnable接口、实现Callable接口和创建线程池,每种方法都提供了代码实现和测试结果。

文章目录

  • 1、继承Thread类
    • 1.1 代码实现
    • 1.2 测试结果
  • 2、实现Runnable接口
    • 2.1 方式一:直接实现Runnable接口
      • 2.1.1 代码实现
      • 2.1.2 测试结果
    • 2.2 方式二:匿名内部类
      • 2.2.1 代码实现
      • 2.2.2 测试结果
  • 3、实现Callable接口
    • 3.1 代码实现
    • 3.2 测试结果
  • 4、创建线程池
    • 4.1 代码实例
    • 4.2 测试结果

1、继承Thread类

/*
 * 创建步骤如下:
 * 1,定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务。因此把run方法称为线程执行体。
 * 2,创建Thread子类了的实例,即创建线程对象。本实例中是new一个ExtendThread,即可创建线程对象,也就是开启了一个线程
 * 3,调用线程对象的start()方法来启动该线程。
 *
 * 调用示例:
 * //循环10次即开启10个线程
 * for (int i = 0; i < 10; i++) {
 *     ExtendThread extendThread = new ExtendThread();
 *     extendThread.start();
 * }
 * */

1.1 代码实现

package com.zyz.mynative.demo03;

/**
 * @author zyz
 * @version 1.0
 * @data 2023/2/15 15:51
 * @Description:继承Thread类,重写run方法(不推荐,因为java的单继承局限性)
 */
public class ExtendThread extends Thread {

    public static void main(String[] args) {
        ExtendThread thread = new ExtendThread();
        thread.start();
    }

    /**
     * 重写Thread类的run(),这个方法称为线程执行体
     */
    @Override
    public void run() {
        doSomething();
    }

    /**
     * 需要处理的任务
     */
    public void doSomething() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "执行" + i);
        }
    }
}

1.2 测试结果

在这里插入图片描述


2、实现Runnable接口

2.1 方式一:直接实现Runnable接口

避免单继承的局限性,方便共享资源,推荐使用

/*
 * 创建步骤如下:
 * 1,定义Runnable接口的实现类,并且实现run方法,这个方法同样是线程执行体
 * 2,创建Runnable实现类的实例,并以此实例对象作为Thread的target来创建Thread类,这个新创建的Thread对象才是真正的线程对象,即开启了新的线程
 * 3,调用线程对象的start()方法来开启该线程
 *
 * 调用示例:
 * //开启10个线程
 * for (int i = 0; i < 10; i++) {
 *     Thread thread = new Thread(new RunnableImpl());
 *     thread.start();
 * }
 * */

2.1.1 代码实现

package com.zyz.mynative.demo03;

/**
 * @author zyz
 * @version 1.0
 * @data 2023/2/15 15:57
 * @Description:
 */
public class RunnableImpl implements Runnable {


    public static void main(String[] args) {
        RunnableImpl runnable = new RunnableImpl();
        Thread thread = new Thread(runnable);
        thread.start();

        /**
         * 简写
         * new Thread(runnable).start();
         */

    }

    /**
     * 实现Runnable接口的run方法,这个方法称为线程执行体
     * */
    @Override
    public void run() {
        doSomething();
    }

    /**
     * 需要处理的任务
     * */
    private void doSomething(){
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "执行" + i);
        }
    }
}

2.1.2 测试结果

在这里插入图片描述

2.2 方式二:匿名内部类

/*
 * 创建步骤如下:
 * 匿名内部类本质上也是一个类实现了Runnable接口,重写了run方法,只不过这个类没有名字,直接作为参数传入Thread类
 *
 * 调用示例:
 * //开启10个线程
 * for (int i = 0; i < 10; i++) {
 *     Anonymous anonymous =new Anonymous();
 *     anonymous.myRun();
 * }
 *
 * */

2.2.1 代码实现

package com.zyz.mynative.demo03;

/**
 * @author zyz
 * @version 1.0
 * @data 2023/2/15 15:57
 * @Description:
 */
public class RunnableImpl2 {


    public static void main(String[] args) {
        RunnableImpl2 test = new RunnableImpl2();
        test.myRun();
    }

    public void myRun(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                doSomething();
            }
        }).start();
    }

    /**
     * 需要处理的任务
     * */
    private void doSomething(){
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "执行" + i);
        }
    }
}

2.2.2 测试结果

在这里插入图片描述


3、实现Callable接口

/*
 * 创建步骤如下:
 * 1,定义实现Callable<V>接口的实现类,实现call方法,这个方法是线程执行体
 * 2,创建Callable<V>实现类的实例,借助FutureTask得到线程执行的返回值
 * 3,将FutureTask的实例,作为Thread的target来创建Thread类
 * 4,调用start方法,开启线程
 *
 * 调用示例:
 * Callable<String> tc = new CallableImpl();
 * FutureTask<String> task = new FutureTask<>(tc);
 * new Thread(task).start();
 * try {
 *     System.out.println(task.get());
 * } catch (InterruptedException | ExecutionException e) {
 *     e.printStackTrace();
 * }
 *
 * 说明:
 * 1.与使用Runnable相比, Callable功能更强大些
 * 2.实现的call()方法相比run()方法,可以返回值
 * 3.方法可以抛出异常
 * 4.支持泛型的返回值
 * 5.需要借助FutureTask类,比如获取返回结果
 * Future接口可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果等。
 * FutureTask是Futrue接口的唯一的实现类
 * FutureTask 同时实现了Runnable, Future接口。它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值
 *
 * */

3.1 代码实现

package com.zyz.mynative.demo03;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author zyz
 * @version 1.0
 * @data 2023/2/15 16:08
 * @Description:
 */
public class CallableImpl implements Callable<String> {

    public static void main(String[] args) {
        Callable<String> tc = new CallableImpl();
        FutureTask<String> task = new FutureTask<>(tc);
        new Thread(task).start();
        try {
            System.out.println(task.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    private int ticket = 5;

    @Override
    public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(doSomething());
        }

        return "出票任务完成";
    }

    public String doSomething() {
        String result = "";
        if (this.ticket > 0) {
            result = "出票成功,ticket=" + this.ticket--;
        } else {
            result = "出票失败,ticket=" + this.ticket;
        }
        return result;
    }
}

3.2 测试结果

在这里插入图片描述


4、创建线程池

/*
 * 创建步骤如下:
 * 1,定义Runnable接口的实现类,或者定义(继承Runnable接口的类)的实现类,并且实现run方法,这个方法是线程执行体
 * 2,创建一个自定义线程个数的线程池
 * 3,实例化Runnable接口的实现类
 * 4,将3步的实例,作为线程池实例的execute方法的command参数,开启线程
 * 5,关闭线程池
 *
 * 调用示例:
 * ExecutorService pool = Executors.newFixedThreadPool(2);
 * ThreadPool threadPool = new ThreadPool("AA");
 * ThreadPool threadPoo2 = new ThreadPool("BB");
 * pool.execute(threadPool);
 * pool.execute(threadPoo2);
 * pool.shutdown();
 *
 * 说明:
 * 示例中创建的是2个线程的线程池
 * execute方法是开启线程方法,实参要求是实现Runnable的类。所以,继承Thread类的子类也可以以线程池的方式开启线程
 *
 * */

4.1 代码实例

package com.zyz.mynative.demo03;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author zyz
 * @version 1.0
 * @data 2023/2/15 16:11
 * @Description:
 */
public class ThreadPool implements Runnable {



    public static void main(String[] args) {
      ExecutorService pool = Executors.newFixedThreadPool(2);
      ThreadPool threadPool = new ThreadPool("AA");
      ThreadPool threadPoo2 = new ThreadPool("BB");
      pool.execute(threadPool);
      pool.execute(threadPoo2);
      pool.shutdown();
    }

    String name;
    public ThreadPool(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        doSomething();
    }

    /**
     * 需要处理的任务
     * */
    private void doSomething() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "执行" + i + ",name=" + this.name);
        }
    }
}

4.2 测试结果

在这里插入图片描述

资料参考:创建线程池的实现方法

相关文章
|
2天前
|
监控 Java
在实际应用中选择线程异常捕获方法的考量
【10月更文挑战第15天】选择最适合的线程异常捕获方法需要综合考虑多种因素。没有一种方法是绝对最优的,需要根据具体情况进行权衡和选择。在实际应用中,还需要不断地实践和总结经验,以提高异常处理的效果和程序的稳定性。
10 3
|
4天前
|
安全 Java UED
Java中的多线程编程:从基础到实践
本文深入探讨了Java中的多线程编程,包括线程的创建、生命周期管理以及同步机制。通过实例展示了如何使用Thread类和Runnable接口来创建线程,讨论了线程安全问题及解决策略,如使用synchronized关键字和ReentrantLock类。文章还涵盖了线程间通信的方式,包括wait()、notify()和notifyAll()方法,以及如何避免死锁。此外,还介绍了高级并发工具如CountDownLatch和CyclicBarrier的使用方法。通过综合运用这些技术,可以有效提高多线程程序的性能和可靠性。
|
2天前
|
监控 Java
捕获线程执行异常的多种方法
【10月更文挑战第15天】捕获线程执行异常的方法多种多样,每种方法都有其特点和适用场景。在实际开发中,需要根据具体情况选择合适的方法或结合多种方法来实现全面有效的线程异常捕获。这有助于提高程序的健壮性和稳定性,减少因线程异常带来的潜在风险。
7 1
|
4天前
|
缓存 Java UED
Java中的多线程编程:从基础到实践
【10月更文挑战第13天】 Java作为一门跨平台的编程语言,其强大的多线程能力一直是其核心优势之一。本文将从最基础的概念讲起,逐步深入探讨Java多线程的实现方式及其应用场景,通过实例讲解帮助读者更好地理解和应用这一技术。
22 3
|
4天前
|
Java Apache Maven
Java将word文档转换成pdf文件的方法?
【10月更文挑战第13天】Java将word文档转换成pdf文件的方法?
14 1
|
8天前
|
Java 编译器
Java“返回类型为 void 的方法不能返回一个值”解决
在 Java 中,如果一个方法的返回类型被声明为 void,那么该方法不应该包含返回值的语句。如果尝试从这样的方法中返回一个值,编译器将报错。解决办法是移除返回值语句或更改方法的返回类型。
|
6天前
|
缓存 安全 Java
使用 Java 内存模型解决多线程中的数据竞争问题
【10月更文挑战第11天】在 Java 多线程编程中,数据竞争是一个常见问题。通过使用 `synchronized` 关键字、`volatile` 关键字、原子类、显式锁、避免共享可变数据、合理设计数据结构、遵循线程安全原则和使用线程池等方法,可以有效解决数据竞争问题,确保程序的正确性和稳定性。
13 2
|
7天前
|
存储 安全 Java
Java-如何保证线程安全?
【10月更文挑战第10天】
|
8天前
|
Java
|
8天前
|
Java
让星星⭐月亮告诉你,jdk1.8 Java函数式编程示例:Lambda函数/方法引用/4种内建函数式接口(功能性-/消费型/供给型/断言型)
本示例展示了Java中函数式接口的使用,包括自定义和内置的函数式接口。通过方法引用,实现对字符串操作如转换大写、数值转换等,并演示了Function、Consumer、Supplier及Predicate四种主要内置函数式接口的应用。
14 1