线程的4种实现方式

一,继承Thread:

  1. 自定义一个类,继承java.lang包下的Thread类
  2. 重写run方法
  3. 将要在线程中执行的代码编写在run方法中
  4. 创建上面自定义类的对象
  5. 调用start方法启动线程。
public class MyThread extends Thread{
	@Override
	public void run() {
		super.run();
		System.out.println("实现run方法");
	}
	public static void main(String[] args) {
		MyThread th = new MyThread();
		th.start();
	}
}

总结:

  • 这种方式的优点是在run方法内可以使用this获取当前线程,无须使用Thread.currentThread方法;
  • 缺点是因为Java的类只能继承一个类,所以继承Thread类之后,就不能继承其他类了,
  • 而且因为任务和代码没有分离,如果多个线程执行相同的任务时,需要多份任务代码。

二、实现Runnable接口

  1. 自定义一个类,实现java.lang包下的Runnable接口
  2. 重写run方法
  3. 将要在线程中执行的代码编写在run方法中
  4. 创建上面自定义类的对象
  5. 创建Thread对象并将上面自定义类的对象作为参数传递给Thread的构造方法中。
  6. 调用start方法启动线程
public class MyRunnable implements Runnable{
	@Override
	public void run() {
		System.out.println("调用runnable类接口");
	}
	public static void main(String[] args) {
		MyRunnable runnable = new MyRunnable();
		//创建线程
		Thread th = new Thread(runnable);
		th.start();
	}
}

总结:

  • 这种方式的优点是因为Java的类可以实现多个接口,所以这个类就可以继承自己需要的类了,
  • 而且任务和代码分离,如果多个线程执行相同的任务时,可以公用同一个任务的代码,
  • 如果需要对它们区分,可以添加参数进行区分。

三、实现Callable接口

  1. 自定义一个类实现java.util.concurrent包下的Callable接口。
  2. 重写Call方法。
  3. 将要在线程中执行的代码编写在call方法中。
  4. 创建ExecutorSercice线程池。
  5. 将自定义的对象放入线程池中。
  6. 获取线程返回结果。
  7. 关闭线程,不在接受新的线程,未执行的完的线程不会被关闭。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
 
public class test04 {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1);
		//通过匿名内部类的方式创建Callable类型对象
		Callable<String>callable = new Callable<String>() {
 
			@Override
			public String call() throws Exception {
				System.out.println(Thread.currentThread().getName());
				Thread.sleep(1000);
				return "测试Callable的返回值";
			}
		};
		Future<String> future = newFixedThreadPool.submit(callable);
		//获取线程的返回结果,主线程在执行
		String str = future.get();
		System.out.println(str);
		newFixedThreadPool.shutdown();//关闭线程池
	}
}

四、创建Executor的工具类创建线程池,通过线程池获取线程

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class test05 {
		public static void main(String[] args) {
			//创建固定线程池对象
			ExecutorService threadPool = Executors.newFixedThreadPool(2);
			Runnable r = new Runnable() {
				@Override
				public void run() {
			System.out.println(Thread.currentThread().getName());
			//如果有一个线程,一个执行完毕后再执行另一个
			//如果有多个线程,可以同时执行多个任务
				}
			};
			threadPool.execute(r);
			threadPool.shutdown();
		}
}

三种方式的对比:

继承Thread

  • 优点:可以直接使用Thread类中的方法,代码简单
  • 缺点:继承Thread类之后就不能继承其他的类

实现Runnable接口

  • 优点:即使自定义类已经有父类了也不受影响,因为可以实现多个接口
  • 缺点:在run方法内部需要获取到当前线程的Thread对象后才能使用Thread中的方法

实现Callable接口

  • 优点:可以获取返回值,可以抛出异常
  • 缺点:代码编写较为复杂

使用哪一种视情况而定!

Runnable比Thread类所具有的优势:

  1. 可以避免java中单继承的局限性;
  2. 任务和线程分离,实现了解耦合,提高代码健壮性
  3. 线程池只能传入Runnable或者Callable类型的对象,不能使用继承的方式,不用newThread.

线程池的使用好处:

  1. 降低资源消耗(减少了频繁的创建和销毁线程),线程池中的线程可以提前创建,而且创建完成任务以后可以不销毁;
  2. 提高响应速度;线程池中的线程可以提前创建线程,任务过来,只需调用启动即可;
  3. 提高线程的可管理性;任务很多,而且每个任务需要消耗的时间比较长。
Java线程实现方式主要有以下几种: 1. **继承Thread类**:这是最简单的一方式,通过继承Thread类并重写run()方法,可以实现线程。但这方式没有考虑线程同步问题,所以不是最安全的。 ```java class MyThread extends Thread { public void run(){ //线程执行代码 } } MyThread thread = new MyThread(); // 创建线程对象 thread.start(); // 启动线程 ``` 2. **实现Runnable接口**:这方式比继承Thread更安全,因为Runnable接口没有继承关系,不会破坏封装性。Runnable接口只包含一个run()方法,所以更简洁。 ```java class MyRunnable implements Runnable { public void run(){ //线程执行代码 } } Thread thread = new Thread(new MyRunnable()); // 创建线程对象 thread.start(); // 启动线程 ``` 3. **实现Callable和Future接口**:这方式适用于需要返回结果的情况。Callable接口比Runnable接口多了一个返回值和异常处理机制。FutureTask类实现了Future接口,可以用来获取异步计算的结果。这方式适用于需要返回结果的复杂任务。 ```java class MyCallable implements Callable<Integer> { public Integer call() throws Exception { //线程执行代码,并返回结果 } } FutureTask<Integer> future = new FutureTask<>(new MyCallable()); // 创建FutureTask对象 thread.start(); // 启动线程,同时将FutureTask对象放入新创建的线程中执行 Integer result = future.get(); // 获取结果 ``` 4. **使用Executor框架**:Java提供了Executor框架,可以方便地创建和管理线程池。这方式适用于需要大量线程的情况,可以避免频繁创建和销毁线程带来的性能开销。 以上就是Java线程的主要实现方式,可以根据具体需求选择合适的方式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值