从设计的角度讨论Java中线程的两种创建方式

简介: Java中的多线程让我们的程序可以同时运行多个任务,即使我们的CPU是单核的。当然我们都明白这种情况下的同时运行,并不是真正的同时运行,而是JVM中的线程调度器根据时间片轮转的方式快速的在不同线程间的切换。

Java中的多线程让我们的程序可以同时运行多个任务,即使我们的CPU是单核的。当然我们都明白这种情况下的同时运行,并不是真正的同时运行,而是JVM中的线程调度器根据时间片轮转的方式快速的在不同线程间的切换。线程调度器让JVM一会运行这个线程,一会运行那个线程,切换的速度很快便我们产生了这些线程好像同时运行的假象。

线程的创建方式有两种,这两种方式究竟有什么不同?性能有什么差异?为什么要设计两种方式呢?带着这些疑问,我们首先回顾一下线程的两种创建方式。

第一种方式,通过实现Runnable接口来创建一个线程:

public class StudyThread{
	public static void main(String[] args){
		MyRunnable myRunnable = new MyRunnable();
		Thread thread = new Thread(myRunnable);
		thread.start();
		
	}
}

class MyRunnable implements Runnable{
	public void run(){
		System.out.println("第一种创建方式");
	}
}


第二种方式,通过继承Thread类来创建一个线程:

public class StudyThreadTwo{
	public static void main(String[] args){
		MyThread myThread = new MyThread();
		myThread.start();
	}
}

class MyThread extends Thread{
	public void run(){
		System.out.println("第二种启动方式");	
	}	
}


通过这两种方式,都能正常创建一个新的线程,性能方面我觉得应该没有多大差异,我们来从设计的角度看一下它们究竟有什么不同。

第一种创建方式是最经常被使用的创建方式。它创建一个线程,需要两个相关类,一个Java提供的Thread类,另一个是要我们自己实现的:实现Runnable接口,并实现run方法。我们要做的就是创建一个Thread对象,在创建时需要一个Runnable类型的参数是需要我们自己实现的。在实际中我们通常使用匿名内部类来实现这种方式,具体如下:

public class StudyThread{
	public static void main(String[] args){
		Thread thread = new Thread(new Runnable(){
			public void run(){
				System.out.println("使用匿名内部类创建线程");
			}
		});
		thread.start();
	}
}

第二种创建方式只需要一个类,就是我们继承自 Thread 类,然后重写 run 方法。这种创建方式相比第一种仿佛更简单。实际上这种简单是有代价的,如果我们从设计的角度(设计原则、设计模式)来考虑的话,就会明白我们为什么在实际中很少用这种方式。

根据设计原则中的单一职责原则,我们的类应该仅实现一类功能,应该有且仅有一个原因引起类的变更,应该让界面显示的类只负责界面显示,数据处理只负责数据处理,控制的只负责控制,最合适的例子就是MVC这种复合设计模式。我们再回到上面的分析,为了便于理解,我们可以将Thread类看做一个工人(a worker),Runnable(中的run方法)就是这个工人的工作(work),在第一种创建方式中,工人是工人,工作是工作(松耦合),工作(Runnable)的变更不会影响到工人(Thread);而在第二种创建方式中,工人与工作绑定死了(紧耦合),工作一变,工人也跟着变,这种牵一发而动全身的编程方式,在简单的工程中还好说,如果在一个及其庞大的项目中的话,如果你的一个地方的修改要引起整个系统的更改的话,那你与你的项目会一起崩溃的。

既然第二种相比第一种有如此弊端,为什么还要设计第一种呢?我觉得我们可以从继承的角度来理解。继承可以让子类自动共享父类的数据和方法,并允许子类添加新的数据或者方法。我们有时就是需要一个工作与工人绑定的,并如果被大量使用的,第二种方式就有优点了。不知道这种理解方式合适与否,欢迎大家积极参与讨论。

相关文章
|
19天前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
58 0
|
1月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
84 16
|
2月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
2月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践
|
3月前
|
Java API 调度
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
307 83
|
3月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
144 0
|
3月前
|
存储 Java 调度
Java虚拟线程:轻量级并发的革命性突破
Java虚拟线程:轻量级并发的革命性突破
259 83
|
4月前
|
移动开发 Java
说一说 Java 是如何实现线程间通信
我是小假 期待与你的下一次相遇 ~