0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Java多线程的用法

科技绿洲 来源:Java技术指北 作者:Java技术指北 2023-09-30 17:07 次阅读

本文将介绍一下Java多线程的用法。

基础介绍

什么是多线程

指的是在一个进程中同时运行多个线程,每个线程都可以独立执行不同的任务或操作。 与单线程相比,多线程可以提高程序的并发性和响应能力。

什么是进程

是指正在运行的程序的实例。

每个进程都拥有自己的内存空间、代码、数据和文件等资源,可以独立运行、调度和管理。在操作系统中,进程是系统资源分配的最小单位,是实现多任务的基础。

Java多线程

Java多线程是指在一个Java程序中同时执行多个线程,它可以提高程序的并发性和响应能力。Java中实现多线程的方式:

  • 继承Thread
  • 实现Runnable接口
  • Executor框架
  • Callable
  • Future
  • 线程池

继承Thread类

继承Thread类是实现多线程的一种方式,只需要继承Thread类并重写run()方法即可。

publicclassThreadDemo{publicstaticvoidmain(String[] args){// 创建10个线程并启动for(inti =0; i <10; i++) { MyThread thread =newMyThread(i); thread.start(); } } }classMyThreadextendsThread{privateintid;publicMyThread(intid){this.id = id; }publicvoidrun(){ System.out.println("Thread "+ id +" is running");try{ Thread.sleep(1000);//vwin
任务执行时间}catch(InterruptedException e) { e.printStackTrace(); } } }

以上代码中,首先创建了一个ThreadDemo类,在main函数中创建了10个线程,并启动这些线程。

每个线程都是MyThread类的实例,MyThread类继承了Thread类,并重写了run()方法,在方法中模拟了一个需要执行1秒钟的任务。

在main函数中,通过创建MyThread类的实例,并调用start()方法启动线程。start()方法会调用线程的run()方法,在run()方法中执行线程的任务。

实现Runnable接口

另一种实现多线程的方式是实现Runnable接口,需要实现run()方法,并将实现了Runnable接口的对象传递给Thread类的构造函数。

publicclassRunnableDemo{publicstaticvoidmain(String[] args){// 创建10个线程并启动for(inti =0; i <10; i++) { Runnable task =newMyTask(i); Thread thread =newThread(task); thread.start(); } } }classMyTaskimplementsRunnable{privateintid;publicMyTask(intid){this.id = id; }publicvoidrun(){ System.out.println("Thread "+ id +" is running");try{ Thread.sleep(1000);// 模拟任务执行时间}catch(InterruptedException e) { e.printStackTrace(); } } }

以上代码中,创建了一个RunnableDemo类,在main函数中创建了10个线程,并启动这些线程。

每个线程都是MyTask类的实例,MyTask类实现了Runnable接口,并重写了run()方法,在方法中模拟了一个需要执行1秒钟的任务。

在main函数中,通过创建MyTask类的实例,并创建一个Thread对象,将Runnable对象作为参数传递给Thread构造方法,最后调用start()方法启动线程。start()方法会调用线程的run()方法,在run()方法中执行线程的任务。

在使用实现Runnable接口实现多线程时,可以更好地分离任务和线程,并提高代码的可扩展性和可维护性。

如果需要添加更多的线程或任务,只需要创建更多的Runnable实例,并创建对应的Thread对象即可,不需要创建更多的线程类,并且可以更好地重用代码。

Executor框架

Executor框架是Java提供的一个线程池框架,用于管理和调度多个线程。通过Executor框架,可以更方便地实现多线程,避免手动管理线程带来的复杂性和风险。

Executor框架的核心接口是Executor和ExecutorService,

  1. Executor是一个简单的线程池接口,只有一个execute()方法,用于提交一个Runnable任务给线程池执行。
  2. ExecutorService是Executor的扩展接口,提供了更多的管理和调度线程的方法,如submit()、shutdown()、awaitTermination()等。

使用Executor框架实现多线程,通常需要以下步骤:

  1. 创建一个ExecutorService对象,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。
  2. 将需要执行的任务封装成一个Runnable或Callable对象,可以使用Java中的匿名内部类或Lambda表达式来创建。
  3. 将任务提交给ExecutorService对象执行,可以使用submit()方法提交Callable对象,或使用execute()方法提交Runnable对象。
  4. 在程序完成时,调用shutdown()方法关闭线程池,或使用awaitTermination()方法等待所有线程执行完毕。
importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclassExecutorDemo{publicstaticvoidmain(String[] args){// 创建一个包含10个线程的线程池ExecutorService executor = Executors.newFixedThreadPool(10);// 提交10个任务给线程池执行for(inti =0; i <10; i++) { executor.execute(newMyTask(i)); }// 关闭线程池executor.shutdown(); } }classMyTaskimplementsRunnable{privateintid;publicMyTask(intid){this.id = id; }publicvoidrun(){ System.out.println("Thread "+ id +" is running");try{ Thread.sleep(1000);// 模拟任务执行时间}catch(InterruptedException e) { e.printStackTrace(); } } }

在上面的例子中,先创建了一个ExecutorDemo类,在main函数中创建了一个包含10个线程的线程池。

每个线程池中的线程都可以执行MyTask类的实例,MyTask类实现了Runnable接口,并重写了run()方法,在方法中模拟了一个需要执行1秒钟的任务。

在main函数中,创建MyTask类的实例,并调用ExecutorService的execute()方法提交给线程池执行。

execute()方法会将任务提交给线程池中的一个空闲线程执行。

最后调用ExecutorService的shutdown()方法关闭线程池。

需要注意的是,shutdown()方法会等待所有线程执行完毕后才会关闭线程池,如果需要立即关闭线程池,可以使用shutdownNow()方法。

Callable实现多线程

Callable是Java中的一个接口,与Runnable接口类似,都用于封装一个线程执行的任务。

不同的是,Callable接口的call()方法可以返回一个结果,而Runnable接口的run()方法没有返回值。

使用Callable实现多线程,通常需要以下步骤:

  1. 创建一个实现了Callable接口的类,实现call()方法,并在方法中编写线程执行的代码。
  2. 创建一个ExecutorService对象,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。
  3. 将Callable对象提交给ExecutorService对象执行,可以使用submit()方法提交。
  4. 调用Future对象的get()方法获取Callable线程执行的结果。
  5. 在程序完成时,调用shutdown()方法关闭线程池,或使用awaitTermination()方法等待所有线程执行完毕。
importjava.util.concurrent.*;publicclassCallableDemo{publicstaticvoidmain(String[] args)throwsException{// 创建一个线程池ExecutorService executor = Executors.newFixedThreadPool(10);// 提交10个Callable任务给线程池执行Future< Integer >[] results =newFuture[10];for(inti =0; i <10; i++) { Callable< Integer > task =newMyTask(i); results[i] = executor.submit(task); }// 输出Callable任务的执行结果for(inti =0; i <10; i++) { Integer result = results[i].get(); System.out.println("Task "+ i +" result is "+ result); }// 关闭线程池executor.shutdown(); } }classMyTaskimplementsCallable<Integer>{privateintid;publicMyTask(intid){this.id = id; }publicIntegercall()throwsException{ System.out.println("Task "+ id +" is running"); Thread.sleep(1000);// 模拟任务执行时间returnid *10; } }

首先创建一个线程池,然后提交10个Callable任务给线程池执行。每个Callable任务都是MyTask类的实例,MyTask类实现了Callable接口,并重写了call()方法,在方法中模拟了一个需要执行1秒钟的任务,并返回一个结果。

详细解释如下:

  1. 创建一个线程池,通过调用Executors的静态方法newFixedThreadPool(10),创建了一个固定大小为10的线程池。
  2. 在for循环中,通过创建MyTask类的实例,将其封装为Callable对象,并通过ExecutorService的submit()方法提交给线程池执行。submit()方法会返回一个Future对象,代表了Callable任务的执行结果。
  3. 在for循环中,通过Future数组记录每个Callable任务的执行结果,可以通过调用get()方法获取Callable任务的执行结果。如果Callable任务还没有执行完成,get()方法会阻塞当前线程,直到任务执行完成并返回结果。如果任务执行过程中发生异常,get()方法会抛出ExecutionException异常。
  4. 在任务完成后,可以通过调用Future对象的get()方法获取任务的执行结果,并打印输出。
  5. 最后调用ExecutorService的shutdown()方法关闭线程池,应该在所有任务执行完成后才能关闭线程池。

注意,在使用Callable实现多线程时,要考虑线程安全、同步机制、任务调度和管理等问题,以确保程序的正确性和稳定性。

同时,由于Callable任务的执行时间可能会比较长,可以设置超时时间来避免任务执行时间过长导致的程序阻塞。

Future实现多线程

Future是Java中的一个接口,用于异步获取任务执行结果。

在多线程编程中,可以使用Future来获取异步任务的执行结果,以便在任务完成后进行处理或展示。

使用Future实现多线程,需要以下步骤:

  1. 创建一个实现了Callable接口的类,实现call()方法,并在方法中编写线程执行的代码。
  2. 创建一个ExecutorService对象,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。
  3. 将Callable对象提交给ExecutorService对象执行,可以使用submit()方法提交,submit()方法会返回一个Future对象。
  4. 调用Future对象的get()方法获取Callable线程执行的结果。如果任务还没有执行完成,get()方法会阻塞当前线程直到任务执行完成并返回结果。
importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.*;publicclassFutureDemo{publicstaticvoidmain(String[] args)throwsException{// 创建一个线程池ExecutorService executor = Executors.newFixedThreadPool(10);// 提交10个Callable任务给线程池执行List< Future< Integer >> results =newArrayList< >();for(inti =0; i <10; i++) { Callable< Integer > task =newMyTask(i); Future< Integer > result = executor.submit(task); results.add(result); }// 输出Callable任务的执行结果for(inti =0; i <10; i++) { Integer result = results.get(i).get(); System.out.println("Task "+ i +" result is "+ result); }// 关闭线程池executor.shutdown(); } }classMyTaskimplementsCallable<Integer>{privateintid;publicMyTask(intid){this.id = id; }publicIntegercall()throwsException{ System.out.println("Task "+ id +" is running"); Thread.sleep(1000);// 模拟任务执行时间returnid *10; } }

在以上示例中:

  1. 首先创建了一个线程池,然后提交10个Callable任务给线程池执行。每个Callable任务都是MyTask类的实例,MyTask类实现了Callable接口,并重写了call()方法,在方法中模拟了一个需要执行1秒钟的任务,并返回一个结果。
  2. 在main函数中,使用List记录每个Callable任务的执行结果的Future对象,并在任务完成后通过调用get()方法获取Callable任务的执行结果。如果任务还没有执行完成,get()方法会阻塞当前线程直到任务执行完成并返回结果。
  3. 最后关闭线程池。

线程池实现多线程

线程池是Java中提供的一个用于管理和复用多个线程的框架,可以有效地提高多线程应用程序的性能和可靠性。

使用线程池实现多线程,通常需要以下步骤:

  1. 创建一个线程池,可以使用Executors类提供的静态方法创建线程池,如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等。
  2. 创建一个实现了Runnable接口或Callable接口的类,实现run()方法或call()方法,并在方法中编写线程执行的代码。
  3. 将Runnable对象或Callable对象提交给线程池执行,可以使用submit()方法提交,submit()方法会返回一个Future对象。
  4. 关闭线程池,可以调用shutdown()方法或shutdownNow()方法。
importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.*;publicclassThreadPoolDemo{publicstaticvoidmain(String[] args)throwsException{// 创建一个包含10个线程的线程池ExecutorService executor = Executors.newFixedThreadPool(10);// 提交10个任务给线程池执行,并记录每个任务的执行结果List< Future< Integer >> results =newArrayList< >();for(inti =0; i <10; i++) { Callable< Integer > task =newMyTask(i); Future< Integer > result = executor.submit(task); results.add(result); }// 等待所有任务执行完成executor.shutdown(); executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);// 输出所有任务的执行结果inttotal =0;for(inti =0; i <10; i++) {try{ Integer result = results.get(i).get(); System.out.println("Task "+ i +" result is "+ result); total += result; }catch(InterruptedException e) { e.printStackTrace(); }catch(ExecutionException e) { System.out.println("Task "+ i +" execution error: "+ e.getCause().getMessage()); } } System.out.println("Total result is "+ total); } }classMyTaskimplementsCallable<Integer>{privateintid;publicMyTask(intid){this.id = id; }publicIntegercall()throwsException{ System.out.println("Task "+ id +" is running"); Thread.sleep(2000);// 模拟任务执行时间if(id %2==0) {thrownewRuntimeException("Task "+ id +" execution error"); }returnid *10; } }

在以上示例中,首先创建了一个包含10个线程的线程池,然后提交10个任务给线程池执行。每个任务都是MyTask类的实例,MyTask类实现了Callable接口,并重写了call()方法,在方法中模拟了一个需要执行2秒钟的任务,并返回一个结果。

其中,如果任务的id是偶数,会抛出一个运行时异常。

在main函数中,使用List记录每个任务的执行结果的Future对象,并在任务完成后通过调用get()方法获取任务的执行结果。

如果任务还没有执行完成,get()方法会阻塞当前线程直到任务执行完成并返回结果。

在所有任务提交给线程池后,调用ExecutorService的shutdown()方法关闭线程池,并调用awaitTermination()方法等待所有任务执行完成。

最后输出所有任务的执行结果,并计算所有任务的执行结果的总和。

总结

总之,Java多线程是提高程序并发性和响应能力的重要手段,需要掌握多线程的实现方式、同步机制、线程之间的通信机制等,以确保多线程程序的正确性和稳定性。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6676

    浏览量

    88191
  • JAVA
    +关注

    关注

    19

    文章

    2934

    浏览量

    103878
  • 程序
    +关注

    关注

    114

    文章

    3693

    浏览量

    80245
  • 多线程
    +关注

    关注

    0

    文章

    275

    浏览量

    19831
  • 代码
    +关注

    关注

    30

    文章

    4641

    浏览量

    67640
收藏 人收藏

    评论

    相关推荐

    Java知识:多线程编程示例#Java

    JAVA 多线程
    学习电子
    发布于 :2022年11月16日 01:45:07

    Java基础学习多线程使用指南

    黑马程序员----- Java基础学习 多线程
    发表于10-08 14:10

    java多线程编程实例 (源程序)

    java 多线程编程实例 import java.awt.*;import javax.swing.*; public class CompMover extends Object {
    发表于10-22 11:48 0次下载

    java多线程设计模式_结城浩

    JAVA 多线程设计模式》通过浅显易懂的文字与实例来介绍 JAVA 线程相关的设计模式概念,并且通过实际的 JAVA程序范例和UML图示来一一解说
    发表于01-05 16:15 0次下载
    <b class='flag-5'>java</b><b class='flag-5'>多线程</b>设计模式_结城浩

    java多线程同步方法

    操作,一个取100块,一个存钱100块。假设账户原本有0块,如果取钱 线程和存钱 线程同时发生,会出现什么结果呢?取钱不成功,账户余额是100.取钱成功了,账户余额是0.那到底是哪个呢?很难说清楚。因此 多线程同步就是要解决这个
    发表于09-27 13:19 0次下载

    多线程细节问题学习笔记

    这一次我们要说下关于final在 多线程的作用,原子性的使用,死锁以及 Java中的应对方案, 线程的局部变量 和 读写锁的介绍 。关于final变量在 多线程的使用 我们如今已经了解到,除非
    发表于11-28 15:34 1072次阅读
    <b class='flag-5'>多线程</b>细节问题学习笔记

    Java多线程总结之Queue

    Java 多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列。 Java提供的 线程安全的Queue可以分为 阻塞队列和非阻塞队列 ,其中阻塞队列的典型例子
    发表于11-28 16:14 3241次阅读
    <b class='flag-5'>Java</b><b class='flag-5'>多线程</b>总结之Queue

    多线程好还是单线程好?单线程多线程的区别 优缺点分析

    摘要:如今单 线程多线程已经得到普遍运用,那么到底 多线程好还是单 线程好呢?单 线程多线程的区别又
    发表于12-08 09:33 8.1w次阅读

    什么是多线程编程?多线程编程基础知识

    摘要: 多线程编程是现代软件技术中很重要的一个环节。要弄懂 多线程,这就要牵涉到多进程。本文主要以 多线程编程以及 多线程编程相关知识而做出的一些结论。
    发表于12-08 16:30 1.2w次阅读

    java学习——java面试【事务、锁、多线程】资料整理

    本文档内容介绍了基于 java学习 java面试【事务、锁、 多线程】资料整理,供参考
    发表于03-13 13:53 0次下载

    Java教程之零点起飞学Java线程资料说明

    多线程编程是提高应用程序性能的重要手段之一。 Java平台从开始就被设计成为 多线程环境,从语言级上支持 多线程。在 Java语言中,提供了创建、启
    发表于02-20 10:41 3次下载
    <b class='flag-5'>Java</b>教程之零点起飞学<b class='flag-5'>Java</b>的<b class='flag-5'>线程</b>资料说明

    java定时器和多线程

    完成一个 javaapplication应用程序,在应用程序主进程中新开一个 线程,此 线程进行死循环,每1秒被激活一次,激活时即在输出显示当前时间。
    发表于06-17 14:11 2684次阅读
    <b class='flag-5'>java</b>定时器和<b class='flag-5'>多线程</b>

    Java多线程应用程序的数据存储库使用改进

    当执行的查询数量很大时,数据存储库通常是高要求系统的瓶颈。延迟批处理执行器(DelayedBatchExecutor)是一个组件,可通过在 Java 多线程应用程序中对所需查询进行批处理来减少所需查询的数量。
    的头像 发表于05-05 20:46 1815次阅读
    <b class='flag-5'>Java</b><b class='flag-5'>多线程</b>应用程序的数据存储库使用改进

    Java多线程永动任务多线程异步任务项目解读

    1. 功能说明 2. 多线程任务示例 2.1 线程池 2.2 单个任务 2.3 任务入口 2.4 结果分析 2.5 源码地址 3. 写在最后 大家好,今天教大家撸一个 Java多线程
    的头像 发表于10-19 11:46 960次阅读

    java实现多线程的几种方式

    Java实现 多线程的几种方式 多线程是指程序中包含了两个或以上的 线程,每个 线程都可以并行执行不同的任务或操作。
    的头像 发表于03-14 16:55 398次阅读