Java中线程的使用

简介: 线程(英语:thread)是操作系统能够进行运算调度的最小单位。

java中如何使用线程

java中创建线程的几种方法:

  • 创建线程(Thread实例)的方式一:继承Thread类创建线程类,让后创建线程实例
  • 创建线程(Thread实例)的方式二:实现Runnable接口创建线程目标类,让后创建线程实例
  • Future接口和FutureTask异步任务类
  • 使用Callable和FutureTask创建异步任务,让后创建线程实例
  • 通过线程池创建线程

继承Thread类创建线程类,让后创建线程实例流程

1).需要继承Thread类,创建一个新的线程子类
2).同时重写run()方法,把需要并发执行的业务代码放入run方法中

代码实现:

public class CreateDemo {

    static int ThreadName = 1;
    //继承Thread类
    static class ThreadDemo extends Thread {
        public ThreadDemo() {
            super("线程-" + ThreadName++);
        }
         //重写run方法,业务逻辑代码写在方法里
        @Override
        public void run() {
            for (int i = 1; i <= 5; ++i) {
                System.out.println(this.getName() + " 第" + i + "次执行");
            }
            System.out.println(this.getName() + " 运行结束");
        }
    }

    public static void main(String[] args) {
        Thread thread = null;
        for (int i = 0; i < 2; ++i) {
            thread = new ThreadDemo();
            thread.start();
        }
    }

}

实现Runnable接口创建线程目标类,让后创建线程实例流程

1.定义一个新类实现Runnable接口
2.实现Runnable接口中的run()抽象方法,将线程代码逻辑存放在该run()实现版本中
3.通过Thread类创建线程对象,将Runnable的实现类实例,作为实际参数传递给Thread类的构造器。由Thread构造器将该Runnable实例赋值给自己的target执行目标属性
4.调用Thread实例的start方法,开启线程

代码实现:

public class CreateDemo2 {

    static int ThreadName = 1;

    //实现Runnable接口
    static class RunTarget implements Runnable {

        //写业务逻辑代码
        @Override
        public void run() {
            for (int i = 1; i <= 5; ++i) {
                System.out.println(Thread.currentThread().getName() + " 第" + i + "次执行");
            }
            System.out.println(Thread.currentThread().getName() + " 运行结束");
        }
    }

    public static void main(String[] args) {
    
        Thread thread = null;
        //方式一:使用实现Runnable的实现类,创建和启动线程
        for (int i = 1; i <= 2; ++i) {
            thread = new Thread(new RunTarget(), "线程-" + ThreadName++);
            thread.start();
        }
        
         //方式二:使用匿名内部类,创建和启动线程
        for (int i = 1; i <= 2; ++i) {
            thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 1; i <= 5; ++i) {
                        System.out.println(Thread.currentThread().getName() + " 第" + i + "次执行");
                    }
                    System.out.println(Thread.currentThread().getName() + " 运行结束");
                }
            },"方式二 线程-" + ThreadName++);
            thread.start();
        }


    }

}

Runnable异步任务的问题:

  • 不能获取异步执行的目标结果(方法没有返回值)
  • 不能取消异步执行的任务

解决方法:

  • 使用“可以进行管理的异步任务”相关类,Future接口和FutureTask异步任务类

FutureTask类的UML关系图
FutureTask类的UML关系图

使用Callable和FutureTask创建异步任务,让后创建线程实例流程

1.创建一个Callable接口的实现类,并实现其call()方法,编写好异步执行的相关逻辑,并且可以由返回值
2.使用Callable实现类的实例,构造一个FutureTask实例
3.使用FutureTask实例,作为Thread构造器的target入参,构造新的Thread线程实例
4.调用Thread实例的start()方法启动新线程,启动新线程的run()方法并执行。其内部的执行过程为:启动Threa实例的run()方法并发执行后,会执行FutureTask实例的run()方法,最终会并发执行Callable实现类中的call()方法。
5.调用FutureTask对象的get()方法,阻塞性的获得并发线程的执行结果
public class CreateDemo3 {

    static class RunnableTask implements Callable<Long> {

        @Override
        public Long call() throws Exception {
            //获取执行前的时间
            long start = System.currentTimeMillis();
            System.out.println(Thread.currentThread().getName() + " 开始运行");
            Thread.sleep(1000);
            System.out.println(Thread.currentThread().getName() + " 运行结束");
            long end = System.currentTimeMillis() - start;
            return end;
        }
    }


    public static void main(String[] args) {
        RunnableTask runnableTask = new RunnableTask();
        FutureTask<Long> futureTask = new FutureTask<>(runnableTask);
        Thread thread = new Thread(futureTask, "线程");
        thread.start();
        //阻塞的获取异步执行的结果
        try {
            System.out.println("异步执行的结果为:线程执行" + futureTask.get() + "ms");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

FutureTask可以处于三种状态

1. 未启动: 在FutureTask.run()还没执行前,FutureTask处于未启动状态。在创建后并且为执行run()方法前。
2. 已启动: Future Task对象的run方法启动并执行过程中,FutureTask处于已启动状态。
3. 已完成: FutureTask正常执行结束,或者FutureTask执行被取消(FutureTask对象的cancel方法),或者FutureTask方法执行抛出异常而导致中断而结束,FutureTask都处于已完成状态。

FutureTask三种状态图解
FutureTask三种状态图解
线程只有处于已完成状态时,调用get()方法才会返回异步执行的结果,处于其它状态时,调用get()方法会阻塞。
获取异步结果

通过线程池创建线程流程

线程池的内容比较多,单独写道另一篇文章里面了。
目录
相关文章
|
5天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
13天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
4天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
|
4天前
|
Java 开发者
Java多线程编程的艺术与实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的技术文档,本文以实战为导向,通过生动的实例和详尽的代码解析,引领读者领略多线程编程的魅力,掌握其在提升应用性能、优化资源利用方面的关键作用。无论你是Java初学者还是有一定经验的开发者,本文都将为你打开多线程编程的新视角。 ####
|
22天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
3天前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
9天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
32 9
|
6天前
|
安全 Java 开发者
Java多线程编程中的常见问题与解决方案
本文深入探讨了Java多线程编程中常见的问题,包括线程安全问题、死锁、竞态条件等,并提供了相应的解决策略。文章首先介绍了多线程的基础知识,随后详细分析了每个问题的产生原因和典型场景,最后提出了实用的解决方案,旨在帮助开发者提高多线程程序的稳定性和性能。
|
12天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
9天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
下一篇
无影云桌面