当前位置:首页 >时尚 >深入浅出、玩转Java多线程 多线我是深入了不起

深入浅出、玩转Java多线程 多线我是深入了不起

2024-07-01 05:12:58 [百科] 来源:避面尹邢网

深入浅出、深入玩转Java多线程

作者:了不起 开发 前端 Java多线程是浅出提高程序并发性和响应能力的重要手段,需要掌握多线程的玩转实现方式、同步机制、多线线程之间的深入通信机制等,以确保多线程程序的浅出正确性和稳定性。

哈喽,玩转大家好,多线我是深入了不起。

Java多线程是浅出Java编程语言的一个特性,它允许程序在同一时间执行多个任务。玩转使用多线程可以充分利用计算机的多线多核处理器,提高程序的深入性能和响应速度。

深入浅出、玩转Java多线程 多线我是深入了不起

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

深入浅出、玩转Java多线程 多线我是深入了不起

基础介绍

什么是玩转多线程

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

深入浅出、玩转Java多线程 多线我是深入了不起

什么是进程

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

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

Java多线程

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

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

继承Thread类

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

public class ThreadDemo {     public static void main(String[] args) {         // 创建10个线程并启动        for (int i = 0; i < 10; i++) {             MyThread thread = new MyThread(i);            thread.start();        }    }} class MyThread extends Thread {     private int id;     public MyThread(int id) {         this.id = id;    }     public void run() {         System.out.println("Thread " + id + " is running");        try {             Thread.sleep(1000);  // 模拟任务执行时间        } catch (InterruptedException e) {             e.printStackTrace();        }    }}

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

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

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

实现Runnable接口

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

public class RunnableDemo {     public static void main(String[] args) {         // 创建10个线程并启动        for (int i = 0; i < 10; i++) {             Runnable task = new MyTask(i);            Thread thread = new Thread(task);            thread.start();        }    }} class MyTask implements Runnable {     private int id;     public MyTask(int id) {         this.id = id;    }     public void run() {         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()方法等待所有线程执行完毕。
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors; public class ExecutorDemo {     public static void main(String[] args) {         // 创建一个包含10个线程的线程池        ExecutorService executor = Executors.newFixedThreadPool(10);         // 提交10个任务给线程池执行        for (int i = 0; i < 10; i++) {             executor.execute(new MyTask(i));        }         // 关闭线程池        executor.shutdown();    }} class MyTask implements Runnable {     private int id;     public MyTask(int id) {         this.id = id;    }     public void run() {         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()方法等待所有线程执行完毕。
import java.util.concurrent.*; public class CallableDemo {     public static void main(String[] args) throws Exception {         // 创建一个线程池        ExecutorService executor = Executors.newFixedThreadPool(10);         // 提交10个Callable任务给线程池执行        Future<Integer>[] results = new Future[10];        for (int i = 0; i < 10; i++) {             Callable<Integer> task = new MyTask(i);            results[i] = executor.submit(task);        }         // 输出Callable任务的执行结果        for (int i = 0; i < 10; i++) {             Integer result = results[i].get();            System.out.println("Task " + i + " result is " + result);        }         // 关闭线程池        executor.shutdown();    }} class MyTask implements Callable<Integer> {     private int id;     public MyTask(int id) {         this.id = id;    }     public Integer call() throws Exception {         System.out.println("Task " + id + " is running");        Thread.sleep(1000);  // 模拟任务执行时间        return id * 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()方法会阻塞当前线程直到任务执行完成并返回结果。
import java.util.ArrayList;import java.util.List;import java.util.concurrent.*; public class FutureDemo {     public static void main(String[] args) throws Exception {         // 创建一个线程池        ExecutorService executor = Executors.newFixedThreadPool(10);         // 提交10个Callable任务给线程池执行        List<Future<Integer>> results = new ArrayList<>();        for (int i = 0; i < 10; i++) {             Callable<Integer> task = new MyTask(i);            Future<Integer> result = executor.submit(task);            results.add(result);        }         // 输出Callable任务的执行结果        for (int i = 0; i < 10; i++) {             Integer result = results.get(i).get();            System.out.println("Task " + i + " result is " + result);        }         // 关闭线程池        executor.shutdown();    }} class MyTask implements Callable<Integer> {     private int id;     public MyTask(int id) {         this.id = id;    }     public Integer call() throws Exception {         System.out.println("Task " + id + " is running");        Thread.sleep(1000);  // 模拟任务执行时间        return id * 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()方法。
import java.util.ArrayList;import java.util.List;import java.util.concurrent.*; public class ThreadPoolDemo {     public static void main(String[] args) throws Exception {         // 创建一个包含10个线程的线程池        ExecutorService executor = Executors.newFixedThreadPool(10);         // 提交10个任务给线程池执行,并记录每个任务的执行结果        List<Future<Integer>> results = new ArrayList<>();        for (int i = 0; i < 10; i++) {             Callable<Integer> task = new MyTask(i);            Future<Integer> result = executor.submit(task);            results.add(result);        }         // 等待所有任务执行完成        executor.shutdown();        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);         // 输出所有任务的执行结果        int total = 0;        for (int i = 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);    }} class MyTask implements Callable<Integer> {     private int id;     public MyTask(int id) {         this.id = id;    }     public Integer call() throws Exception {         System.out.println("Task " + id + " is running");        Thread.sleep(2000);  // 模拟任务执行时间        if (id % 2 == 0) {             throw new RuntimeException("Task " + id + " execution error");        }        return id * 10;    }}

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

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

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

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

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

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

总结

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

责任编辑:武晓燕 来源: Java技术指北 Java多线程程序

(责任编辑:知识)

    推荐文章
    • 花呗是江苏银行批的嘛 用户不同意花呗服务升级会怎样?

      花呗是江苏银行批的嘛 用户不同意花呗服务升级会怎样?支付宝品牌隔离后,有不少人把花呗升级了变成花呗|信用购,其中信用购由江苏银行提供信贷服务,就会问花呗是江苏银行批的嘛?这里就来讨论下这个话题,看看花呗和信用购之间有什么区别和关联,感兴趣的朋友一起了解 ...[详细]
    • 他离去三年,“科学启明星”依旧闪耀

      他离去三年,“科学启明星”依旧闪耀■本报记者 张晴丹2010年冬日的一天,阳光洒向北京市海淀区一栋墙体泛黄脱落的老式板楼。16岁的李星煜同10余名中学生有些许紧张,因为他们要拜访住在这里的一位著名科学家。门一打开,慈祥和蔼的王绶琯侧身 ...[详细]
    • 香港科技大学成立3个科创实验室

      香港科技大学成立3个科创实验室【教育传真】    科技日报讯 记者罗云鹏 通讯员谈家诚 张者昂)1月下旬,记者从香港科技大学获悉,该校成立数据科学基础、再生生物学以及对流与降水3个科创实验室,旨在培育科创人才,促进科研成果转化。  ...[详细]
    • 鳗鱼销海外 产地在江西

      鳗鱼销海外 产地在江西◎本报记者 魏依晨    近日,东北的蔓越莓、四川的鱼子酱,引出全国各地网友纷纷起底自家鲜为人知的特产。    作为一个内陆省份,江西省的“隐藏款”特产竟然是鳗鱼,每年约产鳗鱼2万吨。不仅如此,江西鳗 ...[详细]
    • 贝达药业(300558.SZ)公布消息:凯铭投资解押239万股及质押的511万股延期购回

      贝达药业(300558.SZ)公布消息:凯铭投资解押239万股及质押的511万股延期购回贝达药业(300558.SZ)公布,公司近日接到股东宁波凯铭投资管理合伙企业(有限合伙)(“凯铭投资”)函告,获悉凯铭投资持有公司的部分股份发生质押变动,此次解除质押239万股 ...[详细]
    • 神奇“果冻”精准修复皮肤创面

      神奇“果冻”精准修复皮肤创面水凝胶“果冻”材料。■本报记者 王昊昊 通讯员 陶贤都 曹娇十几年前,当蚕丝蛋白、水凝胶等生物材料领域的很多研究还是“新奇状态”时,施李杨就对多学科交叉研究产生了浓厚兴趣。他的求学之路也颇为交叉——本 ...[详细]
    • 湖南洪江多措并举“水上侗寨”展新颜

      湖南洪江多措并举“水上侗寨”展新颜◎本报记者 俞慧友  通讯员 李 林    红灯笼、拦门酒、竹竿舞、芦笙踩堂、侗歌对唱、侗族百家宴……日前,湖南省怀化市洪江市的“水上侗寨”——托口镇三里村传统侗家好不热闹,村民们正载歌载舞迎新春。  ...[详细]
    • 七旬老人因家庭纠纷喝农药轻生,交警开道及时送医已脱离危险

      七旬老人因家庭纠纷喝农药轻生,交警开道及时送医已脱离危险经及时送医,四川南充营山县一名服药轻生的老人终于脱离生命危险。1月25日中午时分,南充市营山公安交警大队接到群众报警称,一名七旬老人因家庭纠纷、邻里琐事烦心,一时想不开便喝下农药,被家人发现后目前正驾 ...[详细]
    • 华电国际(600027.SH)公布消息:拟购买蒙东能源45.15%股权及福源热电36.86%股权

      华电国际(600027.SH)公布消息:拟购买蒙东能源45.15%股权及福源热电36.86%股权华电国际(600027.SH)公布,上市公司拟向建信投资和中银投资发行普通股A股和可转换公司债券购买其分别持有的蒙东能源45.15%股权和福源热电36.86%股权,其中以发行股份、可转换公司债券支付的 ...[详细]
    • V观财报|康隆达年报造假等被罚300万元

      V观财报|康隆达年报造假等被罚300万元中新经纬1月30日电 康隆达30日披露,公司收到中国证监会《行政处罚决定书》(下称《决定书》),公司被责令改正,给予警告,并被罚300万元。康隆达公告截图《决定书》显示,经查明,康隆达等存在以下违法事 ...[详细]
    热点阅读