Java中实现多线程的两种方式之间的区别
Java提供了线程类Thread来创建多线程的程序。其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象。每个Thread对象描述了一个单独的线程。要产生一个线程,有两种方法:
◆需要从Java.lang.Thread类派生一个新的线程类,重载它的run()方法;
◆实现Runnalbe接口,重载Runnalbe接口中的run()方法。
为什么Java要提供两种方法来创建线程呢?它们都有哪些区别?相比而言,哪一种方法更好呢?
在Java中,类仅支持单继承,也就是说,当定义一个新的类的时候,它只能扩展一个外部类.这样,如果创建自定义线程类的时候是通过扩展 Thread类的方法来实现的,那么这个自定义类就不能再去扩展其他的类,也就无法实现更加复杂的功能。因此,如果自定义类必须扩展其他的类,那么就可以使用实现Runnable接口的方法来定义该类为线程类,这样就可以避免Java单继承所带来的局限性。
还有一点最重要的就是使用实现Runnable接口的方式创建的线程可以处理同一资源,从而实现资源的共享.
1、通过扩展Thread类来创建多线程
假设一个影院有三个售票口,分别用于向儿童、成人和老人售票。影院为每个窗口放有100张电影票,分别是儿童票、成人票和老人票。三个窗口需要同时卖票,而现在只有一个售票员,这个售票员就相当于一个CPU,三个窗口就相当于三个线程。通过程序来看一看是如何创建这三个线程的。
- public class MutliThreadDemo {
- public static void main(String[] args) {
- MutliThread m1=new MutliThread("Window 1");
- MutliThread m2=new MutliThread("Window 2");
- MutliThread m3=new MutliThread("Window 3");
- m1.start();
- m2.start();
- m3.start();
- }
- }
- public class MutliThread extends Thread {
- private int ticket=100;//每个线程都拥有100张票
- public MutliThread (){}
- public MutliThread (String name){
- super(name);
- }
- @Override
- public void run() {
- while(ticket>0){
- System.out.println(ticket--+" is saled by "+Thread.currentThread().getName());
- }
- }
- }
程序中定义一个线程类,它扩展了Thread类。利用扩展的线程类在MutliThreadDemo类的主方法中创建了三个线程对象,并通过start()方法分别将它们启动。
从结果可以看到,每个线程分别对应100张电影票,之间并无任何关系,这就说明每个线程之间是平等的,没有优先级关系,因此都有机会得到CPU的处理。但是结果
显示这三个线程并不是依次交替执行,而是在三个线程同时被执行的情况下,有的线程被分配时间片的机会多,票被提前卖完,而有的线程被分配时间片的机会比较
少,票迟一些卖完。
可见,利用扩展Thread类创建的多个线程,虽然执行的是相同的代码,但彼此相互独立,且各自拥有自己的资源,互不干扰。
2、通过实现Runnable接口来创建多线程
- public class MutliThreadDemo {
- public static void main(String[] args) {
- MutliThread m1=new MutliThread("Window 1");
- MutliThread m2=new MutliThread("Window 2");
- MutliThread m3=new MutliThread("Window 3");
- Thread t1=new Thread(m1);
- Thread t2=new Thread(m2);
- Thread t3=new Thread(m3);
- t1.start();
- t2.start();
- t3.start();
- }
- }
- public class MutliThread implements Runnable{
- private int ticket=100;//每个线程都拥有100张票
- private String name;
- MutliThread(String name){
- this.name=name;
- }
- public void run(){
- while(ticket>0){
- System.out.println(ticket--+" is saled by "+name);
- }
- }
- }
由于这三个线程也是彼此独立,各自拥有自己的资源,即100张电影票,因此程序输出的结果和 1 结果大同小异。均是各自线程对自己的100张票进行单独的处理,互不影响。
可见,只要现实的情况要求保证新建线程彼此相互独立,各自拥有资源,且互不干扰,采用哪个方式来创建多线程都是可以的。因为这两种方式创建的多线程程序能够实现相同的功能。
3、通过实现Runnable接口来实现线程间的资源共享
现实中也存在这样的情况,比如模拟一个火车站的售票系统,假如当日从A地发往B地的火车票只有100张,且允许所有窗口卖这100张票,那么每一个窗口也相当于一个线程,但是这时和前面的例子不同之处就在于所有线程处理的资源是同一个资源,即100张车票。如果还用前面的方式来创建线程显然是无法实现的,这种情况该怎样处理呢?看下面这个程序,程序代码如下所示:
- public class MutliThreadDemo {
- public static void main(String[] args) {
- MutliThread m=new MutliThread();
- Thread t1=new Thread(m);
- Thread t2=new Thread(m);
- Thread t3=new Thread(m);
- t1.start();
- t2.start();
- t3.start();
- }
- }
- public class MutliThread implements Runnable{
- private int ticket=100;//每个线程都拥有100张票
- public void run(){
- while(ticket>0){
- System.out.println(ticket--+" is saled by "+Thread.currentThread());
- }
- }
- }
结果正如前面分析的那样,程序在内存中仅创建了一个资源,而新建的三个线程都是基于访问这同一资源的,并且由于每个线程上所运行的是相同的代码,因此它们执行的功能也是相同的。
可见,如果现实问题中要求必须创建多个线程来执行同一任务,而且这多个线程之间还将共享同一个资源,那么就可以使用实现Runnable接口的方式来创建多线程程序。而这一功能通过扩展Thread类是无法实现的,读者想想看,为什么?
实现Runnable接口相对于扩展Thread类来说,具有无可比拟的优势。这种方式不仅有利于程序的健壮性,使代码能够被多个线程共享,而且代码和数据资源相对独立,从而特别适合多个具有相同代码的线程去处理同一资源的情况。这样一来,线程、代码和数据资源三者有效分离,很好地体现了面向对象程序设计的思想。因此,几乎所有的多线程程序都是通过实现Runnable接口的方式来完成的。
转载于:https://www.cnblogs.com/jdonson/p/6567708.html
Java中实现多线程的两种方式之间的区别相关推荐
- java多线程区别_Java中实现多线程的两种方式之间的区别
Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线 ...
- java中实现多线程的三种方式
java中实现多线程的三种方式 1.实现多线程的方法: 在java中实现多线程的两途径:继承Thread类,实现Runable接口(Callable) 2.继承Thread类实现多线程: 继承类T ...
- Java中HashMap遍历的两种方式
第一种: Map map = new HashMap(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Ma ...
- java中实现同步的两种方式:syschronized和lock的区别和联系
转载自 http://www.cnblogs.com/xiohao/p/4151408.html Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用s ...
- Java中Http连接的两种方式
在java中连接http,介绍两种方法,一种是java的HttpUrlConnection,另一种是apacha公司的httpClient,后者是第三方的类库需要从外部,导入,同时这也是第一次使用外部 ...
- Java中实现多线程的几种方式
1)继承Thread类 实现的步骤: 1)创建Thread类的子类 2)重写run方法 3)创建线程对象 4)启动线程 代码示例: package com.bobo.thread;public cla ...
- Java中创建String的两种方式差异
我们知道创建一个String类型的变量一般有以下两种方法: String str1 = "abcd"; String str2 = new String("abcd&qu ...
- Java中动态代理的两种方式JDK动态代理和cglib动态代理以及区别
视频功能审核通过了,可以看视频啦!记得点关注啊~ 注意:因为网络原因,视频前一两分钟可能会比较模糊,过一会儿就好了 记得点关注啊,视频里的wx二维码失效了,wx搜索:"聊5毛钱的java&q ...
- java如何实现多线程_Java中实现多线程的两种方式
/** * 使用Thread类模拟4个售票窗口共同卖100张火车票的程序 * * 没有共享数据,每个线程各卖100张火车票 * * @author jiqinlin * */public class ...
最新文章
- kernfs_link_sibling
- c语言Inqueue函数用法,C语言用两个栈实现队列(完整版)
- ProtoBuf使用指南(C++)
- intellij设置java中的代码中的import不折叠
- ISA Server服务器故障恢复一例系统盘符更换之后的应对方法
- Teams Bot开发系列:Middleware
- 前端学习(1764):前端调试值之性能分析的方法二
- 楼天成夺Facebook黑客杯季军,已被Facebook录用得到美国绿卡
- php计算对角线,python计算对角线有理函数插值的方法
- python 调用opencv dll_【问题已解决】python 3.6下安装opencv-python解决cv2 DLL load failed: 找不到指定的模块问题...
- 拓端tecdat|Stata中的治疗效果:RA:回归调整、 IPW:逆概率加权、 IPWRA、 AIPW
- C++ 设计模式 面向对象设计原则 相关概念介绍(结合UnrealEngine4)
- 去摘,遥不可及的星~
- 天风掌财社新股认购如何操作?
- 游戏客户端性能(内存)【前篇】
- 交换机到底有什么用?
- 基于springboot项目中使用docker-compose+es+kibana+logstash+mysql 提高数据查询效率
- 【简单实现html页面指定某一个div局部刷新】
- Java中的包(package)详情解释
- Rancher入门到精通-2.0 pening storage failed: block open /prometheus/meta.json: no such file or directory
热门文章
- (持续更新)webstorm快捷键及术语翻译
- 转载:Linux kernel SPI驱动解释
- LINQ to SQL: DataContext.SubmitChanges() 失效问题
- Dockerfile 指令详解2
- 11.8 iotop:动态显示磁盘I/O统计信息
- 上传文件到云服务器存储路径,上传文件到云服务器存储路径
- ZCMU 1958: 机器翻译(技巧性的模拟)
- 阿里云低代码行业智能开放平台开拓行业AI应用新方法
- 为什么SOFA RPC调用30s还不超时?
- 程序员看过来:阿里毕玄提升代码能力的4段经历