java并发之----线程的创建方法

一、线程的创建

(1)继承Thread类

需要实现run方法,通过调用start方法启动线程

public class MyThread extends Thread{
	@Override
	public void run(){//实现run方法
		//以下根据自己的需要来写,这里打印示例1~9
		for(int i=1; i<10; i++){
			System.out.print(i + " ");
		}
	}
}
public class TestMyThread {
	public static void main(String[] args) {
		MyThread m1 = new MyThread();
		m1.start();
	}
}

在这里插入图片描述

(2)实现Runnable接口

同样需要实现run方法,通过Thread调用start()方法来启动线程
与Callable相比,没有返回值

public class MyRunnable implements Runnable{
	@Override
	public void run() {//同样需要实现run方法
		for(int i=0; i<10; i++){
			System.out.print(i + " ");
		}
	}
}
public class TestMyRunnable {
	public static void main(String[] args){
		MyRunnable mr = new MyRunnable();
		//通过Thread调用start()方法来启动线程
		Thread thread = new Thread(mr);
		thread.start();
	}
}

在这里插入图片描述

(3)实现Callable接口

与Runnable相比,Callable提供了call()方法作为线程执行体,类似于run方法,但功能更加强大。
Callable可以有返回值,返回值需要通过FutureTask 进行封装。FutureTask 实现了Future接口和Runnable接口,因而也需要通过Thread调用start()方法来启动线程

public class MyCallable implements Callable<Integer> {
	@Override
	public Integer call() throws Exception {//实现call方法
		int i=0;
		for(; i<10; i++){
			System.out.print(i + " ");
		}
		return i;//返回值
	}
}
public class TestMyCallable {
	public static void main(String[] args) throws InterruptedException, ExecutionException{
		MyCallable mc = new MyCallable();
		FutureTask<Integer> ft = new FutureTask<>(mc);//封装
		Thread thread = new Thread(ft);
		thread.start();
		//返回值通过FutureTask对象的get方法获得
		System.out.println("打印返回值:"+ft.get());
	}
}

在这里插入图片描述

(4)通过线程池(如Executor)创建

Executor 管理多个异步任务的执行,而无需程序员显式地管理线程的生命周期。这里的异步是指多个任务的执行互不干扰,不需要进行同步操作。Executor框架的内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。
Executor主要有三种:

  • CachedThreadPool:一个任务创建一个线程;
  • FixedThreadPool:所有任务只能使用固定大小的线程;
  • SingleThreadExecutor:相当于大小为 1 的 FixedThreadPool。
public class MyExecutor {
	public static void main(String[] args){
		ExecutorService es = Executors.newCachedThreadPool();
		for(int i=0; i<3; i++){//创建3个MyRunnable进程
			es.execute(new MyRunnable());
		}
		es.shutdown();//关闭ExecutorService
	}
}

在这里插入图片描述
Executor接口中之定义了一个方法execute(Runnable command),该方法接收一个Runable实例,它用来执行一个任务,任务即一个实现了Runnable接口的类。ExecutorService接口继承自Executor接口,它提供了更丰富的实现多线程的方法,比如,ExecutorService提供了关闭自己的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 可以调用ExecutorService的shutdown()方法来平滑地关闭 ExecutorService,调用该方法后,将导致ExecutorService停止接受任何新的任务且等待已经提交的任务执行完成(已经提交的任务会分两类:一类是已经在执行的,另一类是还没有开始执行的),当所有已经提交的任务执行完毕后将会关闭ExecutorService。因此我们一般用该接口来实现和管理多线程。

ExecutorService的生命周期包括三种状态:运行、关闭、终止。创建后便进入运行状态,当调用了shutdown()方法时,便进入关闭状态,此时意味着ExecutorService不再接受新的任务,但它还在执行已经提交了的任务,当素有已经提交了的任务执行完后,便到达终止状态。如果不调用shutdown()方法,ExecutorService会一直处在运行状态,不断接收新的任务,执行新的任务,服务器端一般不需要关闭它,保持一直运行即可。

二、总结

(1)关于创建进程,最好通过实现接口方式,因为java不支持多继承,继承了 Thread 类就无法继承其它类,但是可以实现多个接口;
(2)通过Executor来启动线程比使用Thread的start方法更好,更易管理,效率更好(用线程池实现,节约开销)

三、参考

https://github.com/CyC2018/CS-Notes/blob/master/notes/Java 并发.md

扫描二维码关注公众号,回复: 4426188 查看本文章

猜你喜欢

转载自blog.csdn.net/Felix_ar/article/details/84190099