精华内容
下载资源
问答
  • /* * 需求:我们要实现多线程的程序 * 如何实现: * 由于线程是依赖于进程而存在的,所以我们应该先... * 但是呢,Java可以直接调用C/C++写好的程序实现多线程程序 * 由于C/C++去调用系统功能创建进程,然后Java
    package cn.itcast_01;
    /*
     * 需求:我们要实现多线程的程序
     * 如何实现:
     *       由于线程是依赖于进程而存在的,所以我们应该先创建一个进程出来
     *       而进程是由系统创建的,所以我们应该去调用系统功能创建一个进程
     *       但是,Java是不能直接调用系统功能的,所以,我们没有办法直接实现多线程程序
     *       但是呢,Java可以直接调用C/C++写好的程序来实现多线程程序
     *       由于C/C++去调用系统功能创建进程,然后Java去调用这样的东西
     *       然后提供一些类供我们使用。我们就可以实现多线程
     * 
     * 那么Java提供的类是什么?
     *     Thread
     *     通过查看API,我们知道了有两种方法实现多线程
     *     
     * 方式一:继承Thread类
     * 步骤:
     *      A:自定义类MyThread继承Thread类
     *      B:MyThread类里面重写run();
     *             为什么是run()方法呢?
     *                  不是类种的所有代码都需要被线程执行
     *                  而这个时候,为了区分那些代码能够被多线程执行,Java提供了Thread类中的run()方法
     *                  用来包含哪些被线程执行的代码
     *      C:创建对象
     *      D:启动线程
     * 
     */
    public class 如何实现多线程及其多线程方式1的思路 {
    
    	public static void main(String[] args) {
    		// 创建线程对象
    		MyThread my = new MyThread();
    		//启动线程
    		my.run();
    		my.run();
    		//调用run();方法为什么是单线程呢?
    		//因为run();方法的直接调用其实就相当于普通方法调用,所有你看到的是单线程的效果
    		//想要看到多线程的效果,就必须说另一个方法:start()
    		//面试题run()和start()的区别
    		//run():仅仅是封装被线程执行的代码,直接调用依旧是普通方法
    		//start():首先启动了线程,然后再由JVM去调用该线程的run()方法
    
    		MyThread my = new MyThread();
    		my.start();
    		my.start();//IllegalThreadStateException:非法的线程状态异常
    		//为什么呢?
    		//因为这是相当于my线程别调用了两次。而不是两个线程的启动
    		
    		//创建两个线程
    		MyThread my1 = new MyThread();
    		MyThread my2 = new MyThread();
    		
    		my1.start();
    		my2.start();
    	}
    }
    
    展开全文
  • 如果考虑到Java语言特性,继承分为两种:接口继承实现继承。这只是技术层面的问题,即便C++中不存在接口的概念,但它的虚基类实际上也相当于接口。对于OO的初学者来说,他们很希望自己的程序中出现大量的继承,...

    继承是面向对象中很重要的概念。如果考虑到Java语言特性,继承分为两种:接口继承和实现继承。这只是技术层面的问题,即便C++中不存在接口的概念,但它的虚基类实际上也相当于接口。对于OO的初学者来说,他们很希望自己的程序中出现大量的继承,因为这样看起来很OO。但滥用继承会带来很多问题,尽管有时候我们又不得不使用继承解决问题。

    相比于接口继承,实现继承的问题要更多,它会带来更多的耦合问题。但接口继承也是有问题的,这是继承本身的问题。实现继承的很多问题出于其自身实现上,因此这里重点讨论实现继承的问题。

    举个例子(这个例子实在太老套了)。我要实现一个Stack类,我想当然地选择Stack类继承于ArrayList类(你也可以认为我很想OO些或者出于本性的懒惰);现在又有了新的需求,需要实现一个线程安全的Stack,我又定义了一个ConcurrentStack类继承于Stack并覆盖了Stack中的部分代码。

    因为Stack继承于ArrayList,Stack不得不对外暴露出ArrayList所有的public方法,即便其中的某些方法对它可能是不需要的;甚至更糟的是,可能其中的某些方法能改变Stack的状态,而Stack对这些改变并不知情,这就会造成Stack的逻辑错误。

    如果我要在ArrayList中添加新的方法,这个方法就有可能在逻辑上破坏它的派生类Stack、 ConcurrentStack。因此在基类(父类)添加方法(修改代码)时,必须检查这些修改是否会对派生类产生影响;如果产生影响的话,就不得不对派生类做进一步的修改。如果类的继承体系不是一个人完成的,或者是修改别人的代码的情况下,很可能因为继承产生难以觉察的BUG。

    问题还是有的。我们有时会见到这样的基类,它的一些方法只是抛出异常,这意味着如果派生类支持这个方法就重写它,否则就如父类一样抛出异常表明其不支持这个方法的调用。我们也能见到它的一个变种,父类的方法是抽象的,但不是所有的子类都支持这个方法,不支持的方法就以抛出异常的方式表明立场。这种做法是很不友好和很不安全的,它们只能在运行时被“侥幸捕捉”,而很多漏网的异常方法可能会在某一天突然出现,让人不知所措。

    引起上面问题的很重要的原因便是基类和派生类之间的耦合。往往只是对基类做了小小的改动,却不得不重构它们的所有的派生类,这就是臭名昭著的“脆弱的基类”问题。由于类之间的关系是存在的,因此耦合是不可避免的甚至是必要的。但在做OO设计时,当遇到如基类和派生类之间的强耦合关系,我们就要思量思量,是否一定需要继承呢?是否会有其他的更优雅的替代方案呢?如果一定要学究的话,你会在很多书中会看到这样的原则:如果两个类之间是IS-A关系,那么就使用继承;如果两个类之间是Has-A的关系,那么就使用委派。很多时候这条原则是适用的,但IS-A并不能做为使用继承的绝对理由。有时为了消除耦合带来的问题,使用委派等方法会更好地封装实现细节。继承有时会对外及向下暴露太多的信息,在GOF的设计模式中,有很多模式的目的就是为了消除继承。

    关于何时采用继承,一个重要的原则是确定方法是否能够共享。比如DAO ,可以将通用的CRUD 方法定在一个抽象DAO 中,具体的DAO 都派生自这个抽象类。严格的说,抽象DAO 和派生的DAO 实现并不具有IS -A关系,我们只是为了避免重复的方法定义和实现而作出了这一技术上的选择。可以说,使用接口还是抽象类的原则是,如果多个派生类的方法内容没有共同的地方,就用接口作为抽象;如果多个派生类的方法含有共同的地方,就用抽象类作为抽象。当这一原则不适用于接口继承,如果出现接口继承,就会相应地有实现继承(基类更多的是抽象类)。

    现在说说面向接口编程。在众多的敏捷方法中,面向接口编程总是被大师们反复的强调。面向接口编程,实际上是面向抽象编程,将抽象概念和具体实现相隔离。这一原则使得我们拥有了更高层次的抽象模型,在面对不断变更的需求时,只要抽象模型做的好,修改代码就要容易的多。但面向接口编程不意味着非得一个接口对应一个类,过多的不必要的接口也可能带来更多的工作量和维护上的困难。

    相比于继承,OO中多态的概念要更重要。一个接口可以对应多个实现类,对于声明为接口类型的方法参数、类的字段,它们要比实现类更易于扩展、稳定,这也是多态的优点。假如我以实现类作为方法参数定义了一个方法void doSomething(ArrayList list),但如果领导哪天觉得 ArrayList不如LinkedList更好用,我将不得不将方法重构为void doSomething(LinkedList list),相应地要在所有调用此方法的地方修改参数类型(很遗憾地,我连对象创建也是采用ArrayList list = new ArrayList()方式,这将大大增加我的修改工作量)。如果领导又觉得用list存储数据不如set好的话,我将再一次重构方法,但这一次我变聪明了,我将方法定义为void doSomething(Set set),创建对象的方式改为Set set = new HashSet()。但这样仍不够,如果领导又要求将set改回list怎么办?所以我应该将方法重构为void doSomething(Collection collection), Collection的抽象程度最高,更易于替换具体的实现类。即便需要List或者Set固有的特性,我也可以做向下类型转换解决问题,尽管这样做并不安全。

    面向接口编程最重要的价值在于隐藏实现,将抽象的实现细节封装起来而不对外开放,封装这对于Java EE 中的分层设计和框架设计尤其重要。但即便在编程时使用了接口,我们也需要将接口和实现对应起来,这就引出如何创建对象的问题。在创建型设计模式中,单例、工厂方法(模板方法)、抽象工厂等模式都是很好的解决办法。现在流行的控制反转(也叫依赖注入)模式是以声明的方式将抽象与实现连接起来,这既减少了单调的工厂类也更易于单元测试。

    展开全文
  • Java如何实现多线程呢? 文章目录系列文章目录前言一、多线程是什么?1、继承Thread类2、实现Runnable接口二、代码总结 前言 java程序入口是main() ,其实也是mian线程 ,即主线程 一、多线程是什么? (1)java...

    系列文章目录

    Java中如何实现多线程呢?

    前言

    java的程序入口是main() ,其实也是mian线程 ,即主线程

    一、多线程是什么?

    (1)java的程序入口是main() ,其实也是mian线程 ,即主线程
    我们写一个main方法,然后打一个断点
    在这里插入图片描述
    在这里插入图片描述
    (2)如何开启主线程以外的线程
    这是重点
    我们这里只说SE阶段的,即最基础的两种,后面的高级部分再说

    1、继承Thread类

    • 步骤:
    • (1)编写线程类去继承java.lang.Thread类
    • (2)必须重写父类的public void run(){}
    • 在run()中需要编写,你这个线程需要完成的任务。
    • (3)创建线程类对象
    • (4)启动线程:start()
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      如果直接这样,那就不是多线程,只是普通的调用方法而已
      那我们要怎么做呢,我们需要启动线程
      在这里插入图片描述那么他们之间有什么区别呢?
      如果你用run方法 那么会按照顺序执行
      如果你用线程则是不规律的,它会抢CPU的资源,是随机的
      在这里插入图片描述

    2、实现Runnable接口

    • 步骤:
    • (1)编写线程类去实现java.lang.Runnable接口
    • (2)必须实现接口的抽象方法:public void run()
    • 在run()中需要编写,你这个线程需要完成的任务。
    • (3)创建线程类对象
    • (4)启动线程:start()
    • 这个start()方法只有Thread类中才有,说明我们要借用Thread类的对象。
      在这里插入图片描述
      为什么my.start()调用不了呢?
      因为 start本身是继承来的,但是我们这根本没有继承
      在这里插入图片描述
      在这里插入图片描述
      那第二种为什么要存在呢?存在即合理,有很多原因,其中一个原因,接口的数量是没有限制的,这样就能避免Java单继承的缺点,虽然启动麻烦点,但是却是是不可缺少的

    二、代码

    public class TestThread2 {
    	public static void main(String[] args) {
    		System.out.println("hello thread");
    		
    		MyThread my = new MyThread();
    //		my.run();//这么调用,就不是开启多线程,而是普通对象调用方法
    		my.start();//从父类Thread中继承的
    		
    		for (int i = 1; i <=100; i++) {
    			System.out.println("main:" + i);
    		}
    	}
    	
    }
    class MyThread extends Thread{
    
    	@Override
    	public void run() {
    		//例如:这个线程要完成的任务是,打印1-100之间的数字
    		for (int i = 1; i <= 100; i++) {
    			System.out.println("自定义线程:" + i);
    		}
    	}
    	
    }
    

    实现Runnable接口

    package com.atguigu.test02;
    
    public class TestRunnable {
    	public static void main(String[] args) {
    		MyRunnable my = new MyRunnable();
    //		my.start();
    		
    		Thread t = new Thread(my);
    		t.start();
    		
    		for (int i = 1; i <=100; i++) {
    			System.out.println("main:" + i);
    		}
    	}
    }
    
    class MyRunnable implements Runnable {
    
    	@Override
    	public void run() {
    		// 例如:这个线程要完成的任务是,打印1-100之间的数字
    		for (int i = 1; i <= 100; i++) {
    			System.out.println("自定义线程:" + i);
    		}
    	}
    
    }
    

    总结

    两种方式可以作对比,看看它们有啥不同
    整合代码

    package com.atguigu.test02两种最基础的多线程创建方式;
    
    /*Java中如何去实现多线程?
    (1)Java的程序入口是main,其实也是main线程,主线程。
    线程是进程的其中一条执行路径,即一个进程至少有一个线程。那么main线程就是Java程序进程的第一个线程了。
    (2)如何开启main线程以外的其他线程呢?
    这里讲解JavaSE阶段2种,后面会发现还有其他方式。
    方式有两种:①继承Thread类 ②实现Runnable接口
    
    1、继承Thread类
    步骤:
    (1)编写线程类去继承java.lang.Thread类
    (2)必须重写父类的public void run(){}
    在run()中需要编写,你这个线程需要完成的任务。
    (3)创建线程类对象
    (4)启动线程:start()
    
    2、实现Runnable 接口
    步骤:
    (1)编写线程类去实现java.lang.Runnable接口
    (2)必须实现接口的抽象方法:public void run()
    在run()中需要编写,你这个线程需要完成的任务。
    (3)创建线程类对象
    (4)启动线程:start()
    这个start()方法只有Thread类中才有,说明我们要借用Thread类的对象。*/
    
    public class TestThread {
    	public static void main(String[] args) {
    		System.out.println("hello thread");
    		//1、
    		MyThread myThread=new MyThread();
    		myThread.start();
    		
    		//2、
    		MyRunnable myRunnable=new MyRunnable();
    		Thread t=new Thread(myRunnable);
    		t.start();
    		
    		
    		
    		for (int i = 0; i < 100; i++) {
    			System.out.println("main:"+i);
    		}
    	}
    }
    //1、继承Thread类
    class MyThread extends Thread{
    
    	@Override
    	public void run() {
    		for (int i = 0; i < 100; i++) {
    			System.out.println("1继承Thread类的线程:"+i);
    		}
    	}
    }
    //2、实现Runnable 接口
    class MyRunnable implements Runnable{
    
    	@Override
    	public void run() {
    		for (int i = 0; i < 100; i++) {
    			System.out.println("2、实现Runnable接口的线程:"+i);
    		}
    	}
    }
    
    
    展开全文
  • Java虚拟机允许应用程序并发地运行个线程。在Java语言中,线程的实现一般有以下三种方法,其中前两种为最常用的方法。(1)继承Thread类,重写run()方法Thread本质上也是实现了Runnable接口的一个实例,它代表一个...

    Java虚拟机允许应用程序并发地运行多个线程。在Java语言中,多线程的实现一般有以下三种方法,其中前两种为最常用的方法。

    (1)继承Thread类,重写run()方法

    Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()方法。start()方法是一个native(本地)方法,它将启动一个新线程,并执行run()方法(Thread中提供的run()方法是一个空方法)。这种方式通过自定义直接extends Thread,并重写run()方法,就可以启动新线程并执行自己定义的run()方法。需要注意的是:调用start()方法后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行多线程代码是由操作系统决定的。下例给出了Thread的使用方法:

    class MyThread extends Thread {

    public void run() {

    System.out.println("Thread body);//线程的函数体 } } public class Test { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start();//开启线程 } }

    (2)实现Runnable接口,并实现该接口的run()方法

    以下是主要步骤:

    1)自定义类并实现Runnable接口,实现run()方法

    2)创建Thread对象,用实现Runnable接口的对象作为参数实例化该Thread对象

    3)调用Thread的start()方法

    class MyThread implements Runnable {

    public void run() {

    System.out.println("Thread body");

    }

    }

    public class Test {

    public static void main(String[] args) {

    MyThread thread = new MyThread();

    Thread t = new Thread(thread);

    t.start();

    }

    }

    其实,不管是通过继承Thread类还是通过使用Runnable接口来实现多线程的方法,最终还是通过Thread的对象的API来控制线程的。

    (3)实现Callable接口,重写call()方法

    Callable接口实际是属于Executor框架中的功能类,Callable接口与Runnable接口的功能类似,提供了比Runnable更强大的功能,主要表现为以下3点:

    1)Callable可以在任务结束后提供一个返回值,Runnable无法提供这个功能

    2)Callable中的call()方法可以抛出异常,而Runnable的run()方法不能抛出异常

    3)运行Callable可以拿一个Future对象,Future对象表示异步计算的结果,它提供了检查计算是否完成的方法。由于线程属于异步计算模型,因此无法从别的线程中得到函数的返回值,在这种情况下,就可以使用Future来监视目标线程调用call()方法的情况,当调用Future的get()方法以获取结果时,当前线程就会阻塞,直到call()方法结束返回结果

    (4)总结

    以上3中方式中,前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。当需要实现多线程时,一般推荐实现Runnable接口的方式,其原因是

    首先,Thread类定义了多种方法可以被派生类使用或重写。但是只有run()方法是必须被重写的,在run()方法中实现这个线程的主要功能。这当然是实现Runnable接口所需的方法。

    其次,很多Java开发人员认为,一个类仅在她们需要被加强或修改时才会被继承。因此,如果没有必要重写Thread类中的其他方法,那么通过继承Thread的实现方式与实现Runnable接口的效果相同,在这种情况下最好通过实现Runnable接口的方式来创建线程。

    展开全文
  • Java中如何实现多线程? (1)java的程序入口是main方法(main线程/主线程) 线程是进程的其中一条路径,即一个进程至少有一个线程,main线程是java程序进程的第一个线程 (2)如何开启main线程以外的其他线程?...
  • 别急,我们第一步要先得到进入多线程世界的钥匙,也就是如何java实现多线程。在 java实现多线程有四种方式,如下:继承 Thread 类实现 Runnable 接口使用 FutureTask使用 Executor 框架其中继承 Thread 类...
  • 如何实现Java多线程

    2020-06-27 11:35:11
      ...Java虚拟机允许应用程序并发地运行个线程。在Java中,线程的实现一般有以下3中方法: (1)继承Thread类,重写run()方法: Thread本质上也是实现了Runnable接口的一个实例。 ...
  • java虚拟机允许应用程序并发地运行个线程。一、继承Thread类,重写run方法Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方式就是通过Thread类的start()方法public ...
  • 如何实现多线程? 由于线程是依赖进程而存在的,所以我们应该先创建一个进程出来。而进程是由系统创建的。所以我们应该去调用系统的功能创建一个进程。Java是不能直接调用系统功能的,所以,没有办法直接实现多线程程序...
  • 继承“是Java的面向对象学习过程中的大...并且以我的观点,能更好的指导开发工作如何进行继承与扩展的程序设计和编码实现。本文尝试以通俗的语言陈述Java如何恰当的表达“继承”与“扩展”的语义。继承和扩展的...
  • java虚拟机允许应用程序并发地运行个线程。 一、继承Thread类,重写run方法 Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方式就是通过Thread类的start()方法 ...
  • 继承“是Java的面向对象学习过程中的大难题,...并且以我的观点,能更好的指导开发工作如何进行继承与扩展的程序设计和编码实现。本文尝试以通俗的语言陈述Java如何恰当的表达“继承”与“扩展”的语义。继承和扩
  • 姓名: 李小娜[嵌牛导读]: 运行时态性是面向对象程序设计代码重用的一个最强大机制,动态性的概念也可以...[嵌牛鼻子]:通过继承中超类对象引用变量引用子类对象来实现[嵌牛提问] :如何实现运行时java态性?[嵌...
  • Java技巧:用匿名类来实现简化程序调试在Java中,匿名类(Anonymous inner classes)用来处理事件(event handle)。但其实,它们对于debug也很有帮助。本文将介绍如何利用匿名类来简化你的debug。我们该如何调试那些...
  • 原标题:「Java基础知识」如何创建Java线程线程指的是一个程序运行时,会包含个线程同时进行。Java创建线程有三种基本的方法,分别是继承Thread类,实现Runnable接口(推荐的实现方式),实现Callable接口实现Java...
  • 一个进程可以包括一个或个线程,那么如何让一个程序线程运行呢? 这里有两种方法 一个是新线程类继承Thread,在run()方法中写方法体,然后调用start()方法执行 第二种是新线程类implements实现Runnable接口,...
  • 如何写一个 线程程序: 方式一: 1)写一个类继承Thread类,重写run()方法 2)创建这个类的对象,调用start() 代码: MyThread--->提供一个构造方法调用父类的构造方法 为了是给线程提供一个名字! package ...
  • 如何理解Java线程

    2020-08-06 11:40:46
    线程 1、线程和进程的区别: 程序就相当于我们写的代码块 进程就是去执行我们所写的代码块 线程的创建 2、创建线程有三大方法: 一、继承Thread类,并实现run方法 实例如下: 总结:继承Thread类创建线程步骤: 1...
  • java练习-继承和多态05

    2020-04-01 11:09:00
    目录1 继承的概念2 this和super的区别和应用3 继承中的面试题14 继承中的面试题25 方法重写6 final关键字引入7 面试题:final修饰局部变量的问题8 final修饰变量...如何实现继承呢? Java提供了关键字:extends 格...
  • 文章目录封装如何实现封装封装的好处包包的作用如何创建包包命名规范如何导入包类成员的访问修饰符static关键字static修饰符static代码块static变量static方法如何使用继承子类能继承父类的什么子类可以继承父类的...
  • java中很情况下都会使用到线程, 线程也会存在高并发的情况,如何正确的使用线程呢?今天分享一下,如何创建和调用一个线程: 首先说下线程的概念,线程就是一个程序执行的任务,一个任务称呼为一个线程。比如,...
  • 封装定义程序如何引用对象的数据。 封装实际上使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。 适当的封装可以让代码更容易理解和维护,也加强了代码的安全性。 封装实现了高内聚,低耦合。 Ja.
  • 进程和线程有何区别 Java如何实现多线程的 答区别一个程序至少有一个进程 , 一个进程至少有一个线程 线程的划分尺度小于进程 进程在执行过程中拥有独立的内存单元 而多个线程共享内存 从而极大地提高了程序的运 ...
  • 3-Java如何创建线程

    2019-09-03 10:40:03
    Java实现多线程有两种方法:继承Thread类、实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下优势: 可以避免由于Java的单继承特性而...
  • Java多线程---线程的创建和使用主要内容程序、进程、线程的概念Java线程的创建和使用1、继承Thread类与Thread类的主要方法2、实现Runable接口3、线程的调度与设置优先级一、程序、进程、线程的概念1、程序...
  • Java多线程

    2020-07-24 17:52:22
    * 1、Java中如何实现多线程? * (1)Java的程序入口是main,其实也是main线程,主线程。 * 线程是进程的其中一条执行路径,即一个进程至少有一个线程。那么main线程就是Java程序进程的第一个线程了。 * (2)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 486
精华内容 194
关键字:

java程序如何实现多继承

java 订阅