Java——多线程高并发系列之创建多线程的四种方式(Thread、Runnable、Callable、线程池)

简介: Java——多线程高并发系列之创建多线程的四种方式(Thread、Runnable、Callable、线程池)

文章目录:


写在前面

Demo1(继承Thread类,重写run()方法)

Demo2(实现Runnable接口,重写run()方法)

传统写

匿名内部类写法

Demo3(实现Callable接口,重写call()方法)

Demo4(线程池 + Callable接口)

写在前面


历时一个星期,终于整完了Java多线程高并发这个系列的相关内容,这是最后一篇关于多线程的文章了,打算回到最初学习多线程的起点:总结一下创建多线程的四种方式吧。

Demo1(继承Thread,重写run()方法)


package com.szh.begin;
/**
 * 实现多线程的第一种方式:继承Thread类,重写run()方法
 */
public class Test01 {
    static class MyThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " ---> " + i);
            }
        }
    }
    public static void main(String[] args) {
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        t1.setName("t1");
        t2.setName("t2");
        //start方法的作用是:启动一个分支线程,在JVW中开辟一个新的栈空间
        //只要栈空间开辟出来,start方法就结束了,线程就启动成功了,启动成功的线程会自动调用run方法
        //run方法在分支线程的栈底部,main方法在主线程的栈底部,run和main是平级的
        t1.start();
        t2.start();
        //上面的代码也可以写成下面这种形式,只不过需要再来一个有参构造
//        new MyThread("t1").start();
//        new MyThread("t2").start();
    }
}

Demo2(实现Runnable接口,重写run()方法)


传统写法

package com.szh.begin;
/**
 * 实现多线程的第二种方式:实现Runnable接口,重写run()方法
 * 传统写法
 */
public class Test02 {
    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " ---> " + i);
            }
        }
    }
    public static void main(String[] args) {
        new Thread(new MyRunnable(),"t1").start();
        new Thread(new MyRunnable(),"t2").start();
    }
}


匿名内部类写法

package com.szh.begin;
/**
 * 实现多线程的第二种方式:实现Runnable接口,重写run()方法
 * 匿名内部类写法
 */
public class Test03 {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + " ---> " + i);
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + " ---> " + i);
                }
            }
        }).start();
    }
}

Demo3(实现Callable接口,重写call()方法)


package com.szh.begin;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
 * 实现多线程的第三种方式:实现Callable接口,重写call()方法
 * 使用FutureTask接收线程的执行结果
 */
public class Test05 {
    static class MyCallable implements Callable<Object> {
        @Override
        public Object call() throws Exception {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " ---> " + i);
            }
            return "当前执行线程的id为:" + Thread.currentThread().getId();
        }
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //new一个未来任务类对象,参数传入一个Callable接口实现类对象
        FutureTask<Object> task1=new FutureTask<>(new MyCallable());
        FutureTask<Object> task2=new FutureTask<>(new MyCallable());
        //创建两个线程对象,参数传入一个FutureTask对象,之后启动线程
        new Thread(task1).start();
        new Thread(task2).start();
        //获取t1线程的执行结果
        Object obj1=task1.get();
        Object obj2=task2.get();
        System.out.println(obj1);
        System.out.println(obj2);
    }
}


Demo4(线程池 + Callable接口)


package com.szh.begin;
import java.util.concurrent.*;
/**
 * 实现多线程的第三种方式:实现Callable接口,重写call()方法
 * 使用Future接收线程的执行结果
 */
public class Test04 {
    static class MyCallable implements Callable<Object> {
        @Override
        public Object call() throws Exception {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " ---> " + i);
            }
            return "当前执行线程的id为:" + Thread.currentThread().getId();
        }
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建一个固定大小的线程池
        ExecutorService service= Executors.newFixedThreadPool(2);
        //提交执行
        Future<Object> future1=service.submit(new MyCallable());
        Future<Object> future2=service.submit(new MyCallable());
        //获取call()方法的返回值(即线程执行结果的返回值)
        Object obj1=future1.get();
        Object obj2=future2.get();
        //打印
        System.out.println(obj1);
        System.out.println(obj2);
        //关闭线程池
        service.shutdown();
    }
}

相关文章
|
17天前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
47 1
|
2月前
|
数据采集 Java Python
爬取小说资源的Python实践:从单线程到多线程的效率飞跃
本文介绍了一种使用Python从笔趣阁网站爬取小说内容的方法,并通过引入多线程技术大幅提高了下载效率。文章首先概述了环境准备,包括所需安装的库,然后详细描述了爬虫程序的设计与实现过程,包括发送HTTP请求、解析HTML文档、提取章节链接及多线程下载等步骤。最后,强调了性能优化的重要性,并提醒读者遵守相关法律法规。
74 0
|
8月前
|
Java 调度
Java并发编程:深入理解线程池的原理与实践
【4月更文挑战第6天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将从线程池的基本原理入手,逐步解析其工作过程,以及如何在实际开发中合理使用线程池以提高程序性能。同时,我们还将关注线程池的一些高级特性,如自定义线程工厂、拒绝策略等,以帮助读者更好地掌握线程池的使用技巧。
|
算法 Java 调度
Java由浅入深理解线程池设计和原理1
Java由浅入深理解线程池设计和原理1
180 0
|
5月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
4月前
|
存储 缓存 Java
JAVA并发编程系列(11)线程池底层原理架构剖析
本文详细解析了Java线程池的核心参数及其意义,包括核心线程数量(corePoolSize)、最大线程数量(maximumPoolSize)、线程空闲时间(keepAliveTime)、任务存储队列(workQueue)、线程工厂(threadFactory)及拒绝策略(handler)。此外,还介绍了四种常见的线程池:可缓存线程池(newCachedThreadPool)、定时调度线程池(newScheduledThreadPool)、单线程池(newSingleThreadExecutor)及固定长度线程池(newFixedThreadPool)。
|
6月前
|
监控 Java 开发者
深入理解Java并发编程:线程池的原理与实践
【5月更文挑战第85天】 在现代Java应用开发中,高效地处理并发任务是提升性能和响应能力的关键。线程池作为一种管理线程的机制,其合理使用能够显著减少资源消耗并优化系统吞吐量。本文将详细探讨线程池的核心原理,包括其内部工作机制、优势以及如何在Java中正确实现和使用线程池。通过理论分析和实例演示,我们将揭示线程池对提升Java应用性能的重要性,并给出实践中的最佳策略。
|
6月前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
74 1
|
6月前
|
缓存 监控 Java
(十)深入理解Java并发编程之线程池、工作原理、复用原理及源码分析
深入理解Java并发编程之线程池、工作原理、复用原理及源码分析
|
6月前
|
缓存 Java
Java面试题:描述Java中的线程池及其实现方式,详细说明其原理
Java面试题:描述Java中的线程池及其实现方式,详细说明其原理
60 0
下一篇
开通oss服务