Java实现多线程的三种方式

在Java语言中,实现多线程的方式主要有三种:继承Thread类,实现Runnable接口,实现Callable接口,三种方式各有优缺点,下面结合实际代码进行逐一介绍:

1.继承Thread类实现多继承:

优点:Java语言只支持单继承,在继承了其他类之后,无法实现多线程。

缺点:实现简单,结构简介。
实现思路:
①继承Thread类。
②重写run()方法。
③通过子类对象调用start()方法进行线程启动。
④只能通过调用start()方法进行线程启动,直接调用run()方法仅是普通的方法调用。
代码示例:
public class Test extends Thread{
	public void run() {
			System.out.println("创建一个线程");
	}
}
public static void main(String[] args) {
		Test test = new Test();
		test.start();
		//main方法也是一个线程:主线程
		for(int i=0;i<=10;i++){
		System.out.println("主线程");
		}
	}

2.实现Runnable接口类实现多线程:

优点:避免了单一继承的局限性,便于共享资源(由于该方法采用了静态代理设计模式,可创建多个代理对象)
缺点:不能抛出异常,不能返回值。
实现思路:
①实现Runnable接口。
②重写run()方法。
③通过子类对象调用start()方法进行线程启动。
④该方法采用了静态代理设计模式,其中实现了Runnable接口的类相当于真实角色,Thread类相当于代理角色,二者共同实现了Runnable接口,并且Thread具备真实对象引用。
代码示例:
/**
 *实现Runnable接口,重写run方法
 * @author Administrator
 *
 */
public class Programming implements Runnable{

	public void run() {
		for(int i = 0;i<=3;i++){
			System.out.println("helloword...");			
		}
	}
}
public class ProgrammingApp {
	/**
	 * 采用静态代理设计模式
	 * 1.创建真实角色Programming
	 * 2.创建代理角色 Thread+真实对象引用
	 * 3.二者实现相同接口Runnable
	 * @param args
	 */
  public static void main(String[] args) {
	 Programming pro = new Programming();
	 Thread proxy = new Thread(pro);
	 //start方法启动线程
	 proxy.start();
	 //主方法线程
	 for(int i=0; i<=3;i++){
		 System.out.println("helloJava");
	 }
}
}

3.实现Callable<V>接口类实现多线程:

优点:可以返回值,抛出异常。
缺点:实现比较繁琐。
Callable接口Callable接口类似于Runnable接口,实现Callable的接口和实现Runnable的接口都是可被其他线程执行的任务。
Future<V>接口Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。
参数类型: V - 此 Future 的 get 方法所返回的结果类型。
Callable与Runnable的几点不同之处:
1.Callable的规定方法为Call().而Runnable规定的方法为run();
2.call()方法可以抛出异常,而run()方法不可以。
3.Callable的任务执行后可以返回值,运行Callable任务可拿到一个Future对象,Runnable不能有返回值。
实现思路:
创建Callable实现类,重写call()方法
借助执行调度服务ExecutorService获取Future对象
ExecutorService ser = Executor.newFixedThreadPool(int nThreads);
:通过newFixedThreadPool()方法创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
nThreads表示线程池中的线程数。Executor方法提供了管理终止方法,以及可为跟踪一个或多个异步任务执行状态而生成
的Future方法。
Future result =ser.submit(实现类对象);
Submit方法:<T> Future<T> submit(Callable<T> task)
提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。该 Future 的 get 方法在成功完成时将会返回该任务的结果。如果想立即阻塞任务的等待,则可以使用 result = exec.submit(aCallable).get(); 形式的构造。
注:Executors 类包括了一组方法,可以转换某些其他常见的类似于闭包的对象,例如,将 PrivilegedAction 转换为 Callable 形式,这样就可以提交它们了。
参数:
task - 要提交的任务
返回:
表示任务等待完成的 Future
抛出:
RejectedExecutionException - 如果任务无法安排执行
NullPointerException - 如果该任务为 null

获取值get();
⑤停止服务:执行shutdown或shutdownNow方法。
shutdownNow方法会阻止等待任务启动,并试图停止当前正在执行的任务。
shutdown方法在终止前允许执行以前提交的任务。
代码示例:
class Test implements Callable<Integer>{
	public Integer call() throws Exception {
		return 100;
	}
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		ExecutorService ser = Executors.newFixedThreadPool(1);
		Test test = new Test();
		Future<Integer> result =ser.submit(test);
		int num = result.get();
		System.out.println(num);
		
	}

4.总结

上述内容便是Java语言中实现多线程的三种方式,欢迎大家批评指正微笑













猜你喜欢

转载自blog.csdn.net/csdnshenzhen/article/details/72677572
今日推荐