Java开发基础-线程-线程创建有两种方式之二[实现Runable]

  1. 单独定义线程任务的方式.

        实现Runnable接口,并重写抽象方法run来定义任务.

     下面通过简单实例演示

      任务1
class MyRunnable1 implements Runnable{

	@Override
	public void run() {
		for(int i=0;i<1000;i++){
			System.out.println("你是谁啊?");
		}	
	}	
}
      任务2
class MyRunnable2 implements Runnable{

	@Override
	public void run() {
		for(int i=0;i<1000;i++){
			System.out.println("我是修水管的!");
		}
	}
	
}
线程测试:
public class ThreadDemo2 {

	public static void main(String[] args) {
		//实例化任务
		Runnable r1 = new MyRunnable1();
		Runnable r2 = new MyRunnable2();
		//实例化线程
		Thread t1 = new Thread(r1);
		Thread t2 = new Thread(r2);
		
		t1.start();
		t2.start();
	}
}
通过实现Runnable接口重写run方法定义线程任务,将线程与任务分离而解耦合,使线程与任务自由组合易于程序扩展。


<think>我们根据用户的问题,需要回答两个部分: 1. Java中通过线程创建线程的方法有哪些? 2. Runnable和Callable接口的区别是什么? 结合引用内容,我们可以总结如下: 一、通过线程创建线程的方法(主要参考引用[2]和引用[5]): 1. 使用Executors工具类提供的工厂方法(快速创建): - newFixedThreadPool(int nThreads): 创建固定大小的线程- newCachedThreadPool(): 创建可缓存的线程池,线程池大小可根据需要自动调整 - newSingleThreadExecutor(): 创建线程线程- newScheduledThreadPool(int corePoolSize): 创建支持定时及周期性任务执行的线程池 2. 直接使用ThreadPoolExecutor类(自定义创建): 通过ThreadPoolExecutor的构造函数创建,可以更精确地控制线程池的参数(核心线程数、最大线程数、存活时间、任务队列、线程工厂、拒绝策略)。 二、Runnable和Callable接口的区别(主要参考引用[1]、引用[3]和引用[4]): 1. 返回值: - Runnable:没有返回值,run()方法返回void。 - Callable:有返回值,call()方法返回一个泛型类型的值(Future对象可以获取该返回值)。 2. 异常处理: - Runnable:run()方法不能抛出受检异常,只能在方法内部处理。 - Callable:call()方法可以抛出受检异常。 3. 使用方式- Runnable:通常与Thread类结合使用,或者提交给线程池的execute()方法。 - Callable:只能提交给线程池的submit()方法(因为需要返回Future对象)。 下面我们按照要求组织回答。</think>### Java线程创建线程的方法及Runnable与Callable接口区别 #### 一、线程创建线程的方法 1. **通过`Executors`工具类创建**(推荐测试环境使用) ```java // 固定大小线程池 ExecutorService fixedPool = Executors.newFixedThreadPool(4); // 单线程池(保证任务顺序执行) ExecutorService singlePool = Executors.newSingleThreadExecutor(); // 可缓存线程池(自动扩容回收) ExecutorService cachedPool = Executors.newCachedThreadPool(); // 定时任务线程池 ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2); ``` 2. **通过`ThreadPoolExecutor`自定义创建**(生产环境推荐) ```java ThreadPoolExecutor customPool = new ThreadPoolExecutor( 5, // 核心线程数 10, // 最大线程数 60, // 线程空闲存活时间(秒) TimeUnit.SECONDS, // 时间单位 new ArrayBlockingQueue<>(100), // 任务队列 Executors.defaultThreadFactory(), // 线程工厂 new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略 ); ``` 3. **提交任务到线程池** ```java // 提交Runnable任务 customPool.execute(() -> System.out.println("Runnable任务")); // 提交Callable任务 Future<String> future = customPool.submit(() -> { Thread.sleep(1000); return "Callable结果"; }); ``` > **关键点**: > - `execute()`仅提交`Runnable`任务(无返回值) > - `submit()`可提交`Runnable`或`Callable`任务(后者返回`Future`对象)[^4] --- #### 二、Runnable与Callable接口区别 | 特性 | Runnable接口 | Callable接口 | |---------------------|----------------------------------|----------------------------------| | **返回值** | `void run()` 无返回值 | `V call()` 返回泛型结果 | | **异常处理** | 必须内部处理受检异常 | 可直接抛出受检异常 | | **使用场景** | 简单异步任务(如日志写入) | 需获取结果的任务(如计算返回值) | | **线程池提交方式** | `execute()` 或 `submit()` | 只能通过 `submit()` 提交 | | **结果获取** | 无法直接获取执行结果 | 通过 `Future.get()` 获取结果 | **代码示例对比**: ```java // Runnable实现 class PrintTask implements Runnable { @Override public void run() { System.out.println("执行Runnable任务"); } } // Callable实现 class CalcTask implements Callable<Integer> { @Override public Integer call() throws Exception { return 1 + 1; // 返回计算结果 } } // 使用示例 ExecutorService pool = Executors.newFixedThreadPool(2); pool.execute(new PrintTask()); // Runnable提交 Future<Integer> future = pool.submit(new CalcTask()); // Callable提交 System.out.println("计算结果:" + future.get()); // 输出: 计算结果:2 ``` > **核心区别**: > - `Runnable` 适用于**无返回值的简单任务** > - `Callable` 适用于**需要返回值或异常抛出的复杂任务**(如数据库查询、远程调用)[^3] --- #### 三、最佳实践建议 1. **线程池选择**: - CPU密集型任务 → `FixedThreadPool`(核心线程数=CPU核数+1) - IO密集型任务 → `CachedThreadPool`(避免线程阻塞) 2. **接口选择原则**: ```mermaid graph LR A[需要返回值?] -->|是| B[使用Callable] A -->|否| C{需要抛出受检异常?} C -->|是| B C -->|否| D[使用Runnable] ``` 3. **资源管理**: ```java // 正确关闭线程池 pool.shutdown(); // 温和关闭(等待任务完成) // pool.shutdownNow(); // 立即关闭(中断所有线程) ``` > **生产环境警告**:避免使用`Executors.newFixedThreadPool()`的无界队列,推荐自定义`ThreadPoolExecutor`并设置**有界队列**防止OOM[^2]。 --- #### 四、执行流程对比 **Runnable任务流程**: ```mermaid sequenceDiagram Main Thread->>ThreadPool: execute(Runnable) ThreadPool->>Worker Thread: 分配任务 Worker Thread->>Runnable: 执行run() Worker Thread-->>ThreadPool: 任务完成(无返回值) ``` **Callable任务流程**: ```mermaid sequenceDiagram Main Thread->>ThreadPool: submit(Callable) ThreadPool->>Future: 返回Future对象 ThreadPool->>Worker Thread: 分配任务 Worker Thread->>Callable: 执行call() Worker Thread->>Future: 存储结果/异常 Main Thread->>Future: future.get() 获取结果 ``` [^1]: Runnable和Callable是Java创建线程两种核心接口 [^2]: Executors工具类创建线程池存在资源耗尽风险 [^3]: Callable通过Future对象获取返回值并支持异常抛出 [^4]: 线程池使用submit()提交Callable任务 [^5]: Runnable任务通过execute()或submit()提交
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder_Boy_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值