开启线程的四种方式

一、异步委托开启线程
        static void Main(string[] args)
        {
            Action<int, int> a = add;
            a.BeginInvoke(3, 4, null,null);
            Console.WriteLine("main()");
            Console.ReadKey();
        }
        static void add(int a, int b)
        {
            Console.WriteLine(a + b);
        }

![在这里插入图片描述](https://img-blog.csdnimg.cn/20191128153752879.png

二、通过thread类开启线程
using System;
using System.Threading;
public static void Main(string[] args){
			Thread t=new Thread(DownLoadFile_My);//创建了线程还未开启
			t.Start("http://abc/def/**.mp4");//用来给函数传递参数,开启线程
			Console.WriteLine("main()");
			Console.ReadKey();
		}
		
		//thread开启线程要求:该方法参数只能有一个,且是object类型
		static void DownLoadFile_My(object filePath){
			Console.WriteLine("开始下载:"+filePath);
			Thread.Sleep(2000);
			Console.WriteLine("下载完成!");
		}

在这里插入图片描述

三、通过线程池开启线程
		public static void Main(string[] args){
			ThreadPool.QueueUserWorkItem(DownLoadFile_My);
			ThreadPool.QueueUserWorkItem(DownLoadFile_My);
			ThreadPool.QueueUserWorkItem(DownLoadFile_My);
			ThreadPool.QueueUserWorkItem(DownLoadFile_My);
			ThreadPool.QueueUserWorkItem(DownLoadFile_My);
			ThreadPool.QueueUserWorkItem(DownLoadFile_My);
			ThreadPool.QueueUserWorkItem(DownLoadFile_My);
			ThreadPool.QueueUserWorkItem(DownLoadFile_My);
			ThreadPool.QueueUserWorkItem(DownLoadFile_My);
			Console.WriteLine("main()");
			Console.ReadKey();
		}
		static void DownLoadFile_My(object state){
			Console.WriteLine("开始下载...    线程ID:"+Thread.CurrentThread.ManagedThreadId);
			Thread.Sleep(2000);
			Console.WriteLine("下载完成!");
		}

在这里插入图片描述

四、通过任务开启线程

1> Task开启线程

using System;
using System.Threading;
using System.Threading.Tasks;
		public static void Main(string[] args){
			Task t=new Task(DownLoadFile_My);
			t.Start();
			Console.WriteLine("main()");
			Console.ReadKey();
		}
		static void DownLoadFile_My( ){
			Console.WriteLine("开始下载...    线程ID:"+Thread.CurrentThread.ManagedThreadId);
			Thread.Sleep(2000);
			Console.WriteLine("下载完成!");
		}

在这里插入图片描述2> TaskFactory开启线程

		public static void Main(string[] args){
			TaskFactory tf=new TaskFactory();
			tf.StartNew(DownLoadFile_My);
			Console.WriteLine("main()");
			Console.ReadKey();
		}
		static void DownLoadFile_My( ){
			Console.WriteLine("开始下载...    线程ID:"+Thread.CurrentThread.ManagedThreadId);
			Thread.Sleep(2000);
			Console.WriteLine("下载完成!");
		}

在这里插入图片描述

<think>嗯,用户问的是Java开启线程方式有哪些。首先,我得回想一下Java中创建线程的几种方法。记得有两种主要方式:继承Thread类和实现Runnable接口。不过现在可能还有其他方法,比如使用Executor框架或者ForkJoinPool,或者使用Callable接口。 首先,继承Thread类,然后覆盖run方法,然后调用start()方法启动线程。这是最基础的方式,但可能不够灵活,因为Java不支持多继承,所以如果类已经继承了其他类,就不能再继承Thread了。 然后是实现Runnable接口,这也是常见的做法。通过将Runnable实例传给Thread对象,然后启动。这种方式更灵活,因为Java支持实现多个接口,而且可以共享同一个Runnable实例给多个线程,适合资源共享的情况。 接下来是Callable接口和Future,这个可能需要提到,因为Callable可以有返回值,而Runnable不能。使用ExecutorService来提交Callable任务,然后通过Future获取结果。不过这可能属于线程池的范畴。 然后是线程池,使用Executor框架,比如newFixedThreadPool或者newCachedThreadPool,通过提交Runnable或Callable任务来管理线程。这种方式更高效,特别是在处理大量短生命周期的任务时,避免了频繁创建和销毁线程的开销。 还有ForkJoinPool,这是Java 7引入的,用于分治任务,适合递归分解的任务,比如并行处理大数据集。不过可能用户的问题更偏向基础,所以这部分可以作为补充。 另外,可能还有使用定时器Timer类,不过这个可能不是主要的方式,但有时候会用到。或者使用Spring的@Async注解,但这属于框架层面的,可能超出了纯Java的范围,所以可能不需要提到。 需要检查是否有遗漏的方式。比如,是否还有通过匿名内部类或者Lambda表达式来创建线程,这其实属于上述两种方式的简化写法,可以作为示例的一部分。 然后要确保每种方式都有代码示例,并且说明优缺点。比如,继承Thread简单但缺乏灵活性,实现Runnable更推荐,使用线程池更高效,Callable适合需要返回值的情况。 还要注意Java 8之后的版本,比如使用CompletableFuture,这可能属于更高级的并发处理,但用户的问题可能只需要基础方式。 需要分清楚哪些是创建线程方式,哪些是管理线程方式。比如线程池属于管理线程的生命周期,但创建线程方式可能还是基于Thread或Runnable。 可能用户需要的是不同的启动线程方法,所以重点放在继承Thread、实现Runnable、使用Callable和线程池。可能还要提到使用第三方库,比如Guava的ListenableFuture,但可能超出标准库的范围,所以可以省略。 最后,总结每种方式的适用场景,并给出相关问题,比如线程池的优势,Runnable和Callable的区别,如何处理异常等。</think>在 Java 中,开启线程方式主要包括以下几种,按使用场景和复杂度进行分类: --- ### 1. **继承 `Thread` 类** ```java public class MyThread extends Thread { @Override public void run() { System.out.println("通过继承Thread类启动线程"); } } // 启动方式 MyThread thread = new MyThread(); thread.start(); // 必须调用 start(),不能直接调用 run() ``` **特点**: - 简单直观,但类只能继承一个父类,限制了灵活性。 - 不适合资源共享(每个线程需要独立实例)。 --- ### 2. **实现 `Runnable` 接口** ```java public class MyRunnable implements Runnable { @Override public void run() { System.out.println("通过Runnable接口启动线程"); } } // 启动方式 Thread thread = new Thread(new MyRunnable()); thread.start(); ``` **特点**: - 推荐方式,支持多线程共享同一任务(如共享数据)。 - 适合与线程池结合使用。 --- ### 3. **使用 `Callable` 接口 + `Future`(有返回值)** ```java import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class MyCallable implements Callable<String> { @Override public String call() { return "通过Callable返回结果"; } } // 启动方式 ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor.submit(new MyCallable()); System.out.println(future.get()); // 阻塞获取结果 executor.shutdown(); ``` **特点**: - 支持返回值(通过 `Future` 获取)。 - 可抛出异常(需捕获处理)。 - 通常与线程池配合使用。 --- ### 4. **使用线程池(推荐方式)** ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(5); // 固定大小线程池 for (int i = 0; i < 10; i++) { Runnable task = () -> System.out.println("线程池任务执行"); executor.submit(task); } executor.shutdown(); // 关闭线程池 } } ``` **常见线程池类型**: - `newFixedThreadPool(n)`:固定大小线程池。 - `newCachedThreadPool()`:缓存线程池(自动回收空闲线程)。 - `newSingleThreadExecutor()`:单线程串行执行任务。 - `newScheduledThreadPool(n)`:支持定时任务的线程池。 **优点**: - 避免频繁创建和销毁线程的开销。 - 提供任务队列、拒绝策略等高级功能。 --- ### 5. **使用 `ForkJoinPool`(分治任务)** ```java import java.util.concurrent.RecursiveTask; import java.util.concurrent.ForkJoinPool; public class ForkJoinExample extends RecursiveTask<Integer> { @Override protected Integer compute() { return 42; // 模拟计算结果 } public static void main(String[] args) { ForkJoinPool pool = new ForkJoinPool(); ForkJoinExample task = new ForkJoinExample(); Integer result = pool.invoke(task); System.out.println("ForkJoinPool结果:" + result); } } ``` **特点**: - 适用于递归分解任务(如大数据集并行处理)。 - 基于工作窃取算法优化性能。 --- ### 6. **使用 Lambda 表达式简化代码** ```java // 使用 Runnable + Lambda Thread lambdaThread = new Thread(() -> { System.out.println("通过Lambda启动线程"); }); lambdaThread.start(); // 使用线程池 + Lambda ExecutorService executor = Executors.newCachedThreadPool(); executor.submit(() -> System.out.println("线程池 + Lambda")); executor.shutdown(); ``` --- ### 选择建议对比表 | 方式 | 是否支持返回值 | 是否支持异常 | 灵活性 | 推荐场景 | |--------------------|----------------|--------------|--------|------------------------------| | 继承 `Thread` | 否 | 否 | 低 | 简单任务,无需资源共享 | | 实现 `Runnable` | 否 | 否 | 中 | 共享资源,基础多线程开发 | | `Callable` + `Future` | 是 | 是 | 高 | 需返回值或处理异常的任务 | | 线程池 | 否/是(结合Callable) | 否/是 | 极高 | 高并发、资源管理、定时任务 | | `ForkJoinPool` | 是 | 是 | 高 | 分治计算(如大数据处理) | --- ### 注意事项 1. **`start()` vs `run()`** - `start()`:启动新线程执行任务。 - `run()`:直接在主线程执行,不开启线程。 2. **线程安全与同步** - 多线程共享资源时需使用 `synchronized`、`volatile` 或 `Lock` 保证线程安全。 3. **线程池关闭** - 使用 `executor.shutdown()` 正常关闭,避免内存泄漏。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值