Java 创建线程的四种方法

  Jdk 1.5 之前只有继承 Thread 类和实现 Runnable 接口这两种创建线程的方法,在 Jdk 1.5 之后新增了实现 Callable 接口和线程池这两个创建线程的方法。

  1. 继承 Thread 类
  2. 实现 Runnable 接口
  3. 实现 Callable 接口
  4. 线程池

继承 Thread 类

  • 创建继承Thread类的子类,并重写run()方法
  • 创建子类的实例化对象
  • 启动线程——调用该对象的start()方法
class Method1 extends Thread {
    
    
	@Override
	public void run() {
    
    
		System.out.println("继承Thread类的线程");
	}
}

public class CreateThread {
    
    
	public static void createThread() {
    
    
		// 1. 使用Thread子类创建线程
		Thread thread1 = new Method1();// 向上转型
		thread1.start();
	}
	public static void main(String[] args) {
    
    
		createThread();
	}
}

实现 Runnable 接口

  由于 Java 中类的继承是单继承,因此继承 Thread 类来创建线程的方法不够灵活,而实现 Runnable 接口的类依旧可以去继承别的类。而且线程池可以有效的管理实现 Runnable 接口的线程,如果线程池满了,新的线程就会排队等候执行,直到线程池空闲出来为止,而如果是通过继承 Thread 类的线程则会有些麻烦。

  • 创建实现Runnable接口的类,并重写run()方法
  • 创建Thread类对象,使用Thread(Runnable target)构造方法
  • 启动线程——调用该对象的start()方法
class Method2 implements Runnable {
    
    
	@Override
	public void run() {
    
    
		System.out.println("实现Runnable接口的线程");
	}
}
public class CreateThread {
    
    
	public static void createThread() {
    
    
		// 2. 使用Runnable创建线程
		Thread thread2 = new Thread(new Method2());
		thread2.start();
	}
	public static void main(String[] args) {
    
    
		createThread();
	}
}

实现 Callable 接口

  实现 Callable 接口需要重写的是 call() 方法,call() 方法比 run() 方法的功能要更强大一些,call() 方法有返回值,且方法声明可以抛出异常。
  Java5 提供了 Future 接口来代表 Callable 接口里 call() 方法的返回值,并且为 Future 接口提供了一个实现类 FutureTask,这个实现类既实现了 Future 接口,还实现了 Runnable 接口,因此可以作为 Thread 类的 target。在Future 接口里定义了几个公共方法来控制它关联的 Callable 任务。
boolean cancel(boolean mayInterruptIfRunning):视图取消该 Future 里面关联的 Callable 任务。
V get():返回 Callable 里 call() 方法的返回值,调用这个方法会导致程序阻塞,必须等到子线程结束后才会得到返回值。
V get(long timeout,TimeUnit unit):返回 Callable 里 call() 方法的返回值,最多阻塞 timeout 时间,经过指定时间没有返回抛出 TimeoutException。
boolean isDone():若 Callable 任务完成,返回 True。
boolean isCancelled():如果在 Callable 任务正常完成前被取消,返回 True。

创建并启动有返回值的线程的步骤如下:

  • 创建实现Callable接口的类,并重写call()方法
  • 创建一个Callable子类的实例
  • 用Callable子类实例创建FutureTask类对象
  • 用FutureTask类对象为Runnable引用赋值,并调用Thread(Runnable target)创建线程
class Method3 implements Callable<String> {
    
    
	@Override
	public String call() throws Exception {
    
    
		System.out.println("实现Callable接口的线程");
		return "call";
	}
}
public class CreateThread {
    
    
	public static void createThread() {
    
    
		// 3. 使用Callable创建线程
		// 使用FutureTask包装Callable对象
		FutureTask<String> futureTask = new FutureTask<String>(new Method3());
		// 使用FutureTask对象为Runnable引用target赋值
		Thread thread3 = new Thread(futureTask);
		thread3.start();
		try {
    
    
			// 输出call()返回值
			System.out.println(futureTask.get());
		} catch (InterruptedException e) {
    
    
			e.printStackTrace();
		} catch (ExecutionException e) {
    
    
			e.printStackTrace();
		}
	public static void main(String[] args) {
    
    
		createThread();
	}
}

线程池

class Method4 {
    
    
	public static void createThread() {
    
    
		// 一个线程的线程池
//		ExecutorService ex1 = Executors.newSingleThreadExecutor();
		// 固定线程数目的线程池
		ExecutorService ex2 = Executors.newFixedThreadPool(5);
		// 带缓存的线程池
//		ExecutorService ex3 = Executors.newCachedThreadPool();
		for (int i = 0; i < 5; i++) {
    
    
			// execute只能接受Runnable类型参数
			// submit可以接受Runnable和Callable
			ex2.execute(new Runnable() {
    
    
				@Override
				public void run() {
    
    
					System.out.println("线程池中的线程" + Thread.currentThread().getName());
				}
			});
		}
		// 关闭资源
		ex2.shutdown();
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40395874/article/details/115222503
今日推荐