精华内容
下载资源
问答
  • 创建线程有几种方式

    2020-09-09 22:49:30
    创建线程有几种方式 **1) 继承thread:**本质是是实现了runnable接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过tead的start()死大特start()是一个native内体武方法它将启动一个新线程,执行...

    创建线程有几种方式

    **1) 继承thread类:**本质是是实现了runnable接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过tead类的start()死大特start()是一个native内体武方法它将启动一个新线程,执行run()
    **2) 实现runnable接口:**如果自己的类已经extends 另一个类,就无法直接extends Thread,此时,可以实现一个Runnable 接口。
    3) 实现卡了波callable接口:Callabled 接口有点像是Runnable 接口的增强版 ,它以call()方法作为线程执行体,call()方法比run()方法功能更强大。call()方法可以有返回
    4) 通过线程池方法:常用的线程池有:
    1).newSingleThreadExecutor:创建一个单线程的线程,按照任务的提交顺序执行
    2).newFixedThreadPool:创建固定大小的线程池提交一个任务创建一个线程,直到达到线程池最大大小
    3).newCachedThreadPool:创建一个可缓存的线程池,大小取决于jvm
    4).newScheduledThreadPool:创建一个无限大小的线程池,支持定时和周期性执行任务
    5).newSingleThreadExecutor:创建一个单线程的线程, 支持定时和周期性执行任务

    展开全文
  • Java创建线程有几种方式? Java 创建线程有两种方式: 1. 继承Thread,并重写run()方法 2. 实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread public static void main(String[] ...

                            Java创建线程有几种方式?

     Java 创建线程有两种方式:

    1. 继承Thread类,并重写run()方法
    2. 实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread

    public static void main(String[] args) {
        // 第一种
        MyThread myThread = new MyThread();
        myThread.start();
        // 第二种
        new Thread(() -> System.out.println("自己实现的run-2")).start();
    }
    
    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("自己实现的run-1");
        }
    }

    Java5 之后的ExecutorsExecutors工具类可以用来创建线程池。

    小哥:Executors工具类是用来创建线程池的,这个线程池可以指定线程个数,也可以不指定,也可以指定定时器的线程池,它有如下常用的方法:

    newFixedThreadPool(int nThreads):创建固定数量的线程池
    newCachedThreadPool():创建缓存线程池
    newSingleThreadExecutor():创建单个线程
    newScheduledThreadPool(int corePoolSize):创建定时器线程池

    hread里的run()方法具体是怎么实现的吗?

    Thread 中的run()方法里东西很少,就一个 if 判断:

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

    有个target对象,会去判断该变量是否为空,非空的时候,去执行target对象中的run()方法,否则啥也不干。而这个target对象,就是我们说的Runnable

    Runnable

    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }

    这个抽象方法也是run()!如果我们使用Runnable接口,就需要实现这个run()方法。由于这个Runnable类上面标了@FunctionalInterface注解,所以可以使用函数式编程。

     

    假如用第一种方式:继承了Thread类,然后重写了run()方法,那么它就不会去执行上面这个默认的run()方法了(即不会去判断target),会执行我重写的run()方法逻辑。

    假如是用的第二种方式:实现Runnable接口的方式,那么它会执行默认的run()方法,然后判断target不为空,再去执行我在Runnable接口中实现的run()方法。

     

    那如果我既继承了Thread类,同时我又实现了Runnable接口,比如这样,最后会打印什么信息出来呢?

    public static void main(String[] args) {
        new Thread(() -> System.out.println("runnable run")) {
            @Override
            public void run() {
                System.out.println("Thread run");
            }
        }.start();
    }

    “Thread run”

    其实是 new 了一个对象(子对象)继承了Thread对象(父对象),在子对象里重写了父类的run()方法;然后父对象里面扔了个Runnable进去,父对象中的run()方法就是最初那个带有 if 判断的run()方法。

    好了,现在执行start()后,肯定先在子类中找run()方法,找到了,父类的run()方法自然就被干掉了,所以会打印出:Thread run。

     Java 语言本身的父子继承关系,会优先执行子类重写的方法而已

    在这里插入图片描述

    展开全文
  • 这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家。 点赞再看,养成习惯~ 微信搜索【武哥聊编程】,关注这个 Java 菜鸟。...Java 创建线程种方式: 继承Thread,并重写run(...

    这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家。
    点赞再看,养成习惯~ 微信搜索【武哥聊编程】,关注这个 Java 菜鸟。

    昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的问题:你说一说 Java 创建线程都有哪些方式?

    这哥们心中窃喜,这个老生常谈的问题早已背的滚瓜烂熟,于是很流利的说了出来。

    Java 创建线程有两种方式:

    1. 继承Thread类,并重写run()方法
    2. 实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread

    面试官:(拿出一张白纸)那你把这两种方式写一下吧!

    小哥:(这有何难!)好~

    public static void main(String[] args) {
    	// 第一种
        MyThread myThread = new MyThread();
        myThread.start();
    	// 第二种
        new Thread(() -> System.out.println("自己实现的run-2")).start();
    }
    
    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("自己实现的run-1");
        }
    }
    

    面试官:嗯,那除了这两种,还有其他创建线程的方法吗?

    这些简单的问题难不倒这哥们,于是他想到了 Java5 之后的ExecutorsExecutors工具类可以用来创建线程池。

    小哥:Executors工具类是用来创建线程池的,这个线程池可以指定线程个数,也可以不指定,也可以指定定时器的线程池,它有如下常用的方法:

    newFixedThreadPool(int nThreads):创建固定数量的线程池
    newCachedThreadPool():创建缓存线程池
    newSingleThreadExecutor():创建单个线程
    newScheduledThreadPool(int corePoolSize):创建定时器线程池

    面试官:嗯,OK,咱们还是针对你刚刚写的代码,我再问你个问题。

    此时这哥们有种不祥的预感,是不是自己代码写的有点问题?或者要问我底层实现?

    面试官:你写的两种创建线程的方式,都涉及到了run()方法,你了解过Thread里的run()方法具体是怎么实现的吗?

    果然问到了源码了,这哥们之前看了点,所以不是很慌,回忆了一下,向面试官道来。

    小哥:emm……Thread 中的run()方法里东西很少,就一个 if 判断:

    @Override
    public void run() {
    	if (target != null) {
    		target.run();
    	}
    }
    

    有个target对象,会去判断该变量是否为空,非空的时候,去执行target对象中的run()方法,否则啥也不干。而这个target对象,就是我们说的Runnable

    /* What will be run. */
    private Runnable target;
    

    面试官:嗯,那这个Runnable类你了解过吗?
    小哥:了解过,这个Runnable类很简单,就一个抽象方法:

    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
    

    这个抽象方法也是run()!如果我们使用Runnable接口,就需要实现这个run()方法。由于这个Runnable类上面标了@FunctionalInterface注解,所以可以使用函数式编程。

    那小哥接着说:(突然自信起来了)所以这就对应了刚才说的两种创建线程的方式,假如我用第一种方式:继承了Thread类,然后重写了run()方法,那么它就不会去执行上面这个默认的run()方法了(即不会去判断target),会执行我重写的run()方法逻辑。

    假如我是用的第二种方式:实现Runnable接口的方式,那么它会执行默认的run()方法,然后判断target不为空,再去执行我在Runnable接口中实现的run()方法。

    面试官:OK,可以,我再问你个问题。

    小哥:(暗自窃喜)

    面试官:那如果我既继承了Thread类,同时我又实现了Runnable接口,比如这样,最后会打印什么信息出来呢?

    面试官边说边拿起刚刚这小哥写的代码,对它进行了简单的修改:

    public static void main(String[] args) {
        new Thread(() -> System.out.println("runnable run")) {
            @Override
            public void run() {
                System.out.println("Thread run");
            }
        }.start();
    }
    

    这小哥,突然有点懵,好像从来没想过这个问题,一时没有什么思路,于是回答了个:会打印 “Thread run” 吧……

    面试官:答案是对的,但是为什么呢?

    这小哥一时没想到原因,于是面试官让他回去可以思考思考,就继续下一个问题了。

    亲爱的读者朋友,你们知道为什么吗?你们可以先思考一下。

    其实这个答案很简单,我们来分析一下代码便知:其实是 new 了一个对象(子对象)继承了Thread对象(父对象),在子对象里重写了父类的run()方法;然后父对象里面扔了个Runnable进去,父对象中的run()方法就是最初那个带有 if 判断的run()方法。

    好了,现在执行start()后,肯定先在子类中找run()方法,找到了,父类的run()方法自然就被干掉了,所以会打印出:Thread run。

    如果我们现在假设子类中没有重写run()方法,那么必然要去父类找run()方法,父类的run()方法中就得判断是否有Runnable传进来,现在有一个,所以执行Runnable中的run()方法,那么就会打印:Runnable run 出来。

    说白了,就是问了个 Java 语言本身的父子继承关系,会优先执行子类重写的方法而已,只是借这个场景,换了个提问的方式,面试者可能一时没反应过来,有点懵也是正常的,如果直接问,傻子都能回答的出来。

    后记:通过这道简单的面试题,帮大家分析了一下在创建线程过程中的源码,可以看出来,面试过程中,面试官更加看重一些原理性的东西,而不是背一下方式就行了。同时也能看的出,面试大厂,需要做好充分的准备。另外,在面试的时候要冷静,可能有些问题并没有太难,回答不出来只是当时太紧张造成的。

    这篇文章就写到这,最后祝大家都能面试成功。

    如果觉得有帮助,希望老铁们来个三连击,给更多的人看到这篇文章

    1、关注我的原创微信公众号「武哥聊编程」,专注于Java、数据结构和算法、微服务、中间件等技术分享,保证你看完有所收获。

    2、给俺点个赞呗,可以让更多的人看到这篇文章,顺便激励下我继续写作,嘻嘻。

    作者info

    【作者】:武哥
    【公众号】:武哥聊编程。欢迎大家关注~
    【作者简介】:同济大学,硕士。先后在华为、科大讯飞、拼多多采坑。一个自学 Java 的菜鸟,期待你的关注。

    点赞是对我最大的鼓励
    ↓↓↓↓↓↓

    展开全文
  • 源码中说的创建线程种方式类thread和接口runable;网上第三种:实现Callable接口,结合FutureTask创建线程,这种方式我们查看源码也可以看出它实际上也属于实现Runable接口方式:public class FutureTask<V&...

    在网上搜索线程创建的集中方式,大约都是多的三种或者四种,我们看下jdk的源码怎么说的?

    691f85cee896505f89597f4ca6ac2ea1.png

    源码中说的创建线程有两种方式类thread和接口runable;

    网上第三种:实现Callable接口,结合FutureTask创建线程,这种方式我们查看源码也可以看出它实际上也属于实现Runable接口方式:

    public class FutureTask<V> implements RunnableFuture<V> {}
    public interface RunnableFuture<V> extends Runnable, Future<V> {}

    还有第四种线程池的创建,他们的任务其实都是上面最基本的两个实现的衍生。

    Thread与Runanble的区别:thread是对线程的抽象,runable是对任务的抽象


    Thread中的方法:

    stop():jdk对这些Deprecated的方法不建议使用,带有很高的强制性,终止线程很野蛮,直接结束掉,不管当前资源有没有正常释放掉。

    interrupt():对线程发起中断,并不是正真的终止线程,给线程一个中断标志位,线程不会立即停止,也可以完成不用理会,这说明,在jdk里面,线程是协作式的,而不是抢占式的

    //在程序中,如果所有的非守护线程都已经执行完毕,那么守护线程将立即被结束,因此守护线程的finally子句不一定能够执行
    public class DaemonThread {
    	private static class UseThread extends Thread {
    		@Override
    		public void run() {
    			try {
    				while (!isInterrupted()) {
    					System.out.println(Thread.currentThread().getName() + " I am extends Thread.");
    				}
    				System.out.println(Thread.currentThread().getName() + " interrupt flag is " + isInterrupted());
    			} finally {
    				//守护线程中finally不一定起作用
    				System.out.println(" .............finally");
    			}
    		}
    	}
    
    	public static void main(String[] args) throws InterruptedException, ExecutionException {
    		UseThread useThread = new UseThread();
    		//useThread.setDaemon(true);
    		useThread.start();
    		Thread.sleep(5);
    		useThread.interrupt();
    	}
    }

    08ea040a0b9ad505bdbe139572b634da.png

    Thread.interrupted()获取当前线程的状态是否被中断,如果中断,会重置中断状态。

    测试如下:

    Thread.currentThread().interrupt();
    System.out.println("mainThread interrupt:" + Thread.currentThread().isInterrupted());
    System.out.println("mainThread interrupt:" + Thread.interrupted());
    System.out.println("mainThread interrupt:" + Thread.currentThread().isInterrupted());
    
    // 运行结果如下:
    mainThread interrupt:false
    mainThread interrupt:false
    mainThread interrupt:false

    源码如下:

    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

    不建议在类中定义一个isCannel标志位来中断线程,如果run方法中有sleep()或者wait()等阻塞方法,在外面设置setCannel(true),根本没有,而thread中的中断方法都throw 了一个InterruptedException,对于外界的中断会有感知,下面是一个测试例子:

    public class EndThread {
        public static class UseThread extends Thread {
            public  UseThread(String name) {
                super(name);
            }
    
            @Override
            public void run() {
                String threadName = Thread.currentThread().getName();
                System.out.println(threadName+" interrupt flag=" + this.isInterrupted());
                while (!isInterrupted()) {
    //                while (Thread.interrupted()) {
    //                while(true) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        System.out.println("flag:" + Thread.currentThread().isInterrupted());
                        // Thread.currentThread().interrupt();
                    }
    
                   System.out.println(threadName + "isRuning");
                   System.out.println(threadName + "inner interrupt flag="+isInterrupted());
                }
                System.out.println(threadName+" 11 interrupt flag = " + isInterrupted());
            }
        }
        public static void main(String args[]) throws InterruptedException {
            Thread endThread =new UseThread("endThread");
            endThread.start();
            Thread.sleep(200);
            endThread.interrupt();
        }
    }

    运行结果如下,外面发生一个中断操作,子线程中虽然在sleep,但是立马感知到了中断,然后进入了catch异常里面,此时将这个InterruptedException异常又将线程的flag改为false,线程又继续再往下执行,这样做的好处就是给开发人员留有余地,可以再catch中进行一些资源的释放等工作,如果这时想中断线程,可以在catch中手动interrupt()中断线程。

    fe97447e1336e522844b3b1a5e5e485a.png

    join(): 可以实现线程的顺序执行,当前线程需要等待previousThread线程终止之后才从thread.join返回。简单来说,就是线程没有执行完之前,会一直阻塞在join方法处。

    join(long millis): 至多等待多少毫秒

    public class UseJoin {
    
        static class Goddess implements Runnable {
            private Thread thread;
    
            public Goddess(Thread thread) {
                this.thread = thread;
            }
    
            public Goddess() {
            }
    
            public void run() {
                System.out.println("Goddess开始排队打饭.....");
                try {
                    if (thread != null)
                        thread.join();
                } catch (InterruptedException e) {
                }
                SleepTools.second(2);//休眠2秒
                System.out.println(Thread.currentThread().getName() + " Goddess打饭完成.");
            }
        }
    
        static class GoddessBoyfriend implements Runnable {
    
            public void run() {
                SleepTools.second(2);//休眠2秒
                System.out.println("GoddessBoyfriend开始排队打饭.....");
                System.out.println(Thread.currentThread().getName() + " GoddessBoyfriend打饭完成.");
            }
        }
    
        public static void main(String[] args) throws Exception {
    
            Thread lison = Thread.currentThread();
            GoddessBoyfriend goddessBoyfriend = new GoddessBoyfriend();
            Thread gbf = new Thread(goddessBoyfriend);
            Goddess goddess = new Goddess(gbf);
            //Goddess goddess = new Goddess();
            Thread g = new Thread(goddess);
            g.start();
            gbf.start();
            System.out.println("lison开始排队打饭.....");
            g.join();
            //SleepTools.second(2);//让主线程休眠2秒
            System.out.println(Thread.currentThread().getName() + " lison打饭完成.");
        }
    }
    
    // 运行结果如下:
    Connected to the target VM, address: '127.0.0.1:56883', transport: 'socket'
    lison开始排队打饭.....
    Goddess开始排队打饭.....
    GoddessBoyfriend开始排队打饭.....
    Thread-0 GoddessBoyfriend打饭完成.
    Thread-1 Goddess打饭完成.
    main lison打饭完成.
    展开全文
  • ProductInfo productInfo = new ProductInfo { CategoryId =12, TypeId =23 ProName ="abc", ProCode ="ddd" }; 这种方式需要事先定义吗???????????、
  • 创建线程池几种方式

    千次阅读 2020-05-04 22:15:27
    创建线程池几种方式一、Executors二、ThreadPoolExecutor 一、Executors Executors是一个线程相关的工具。主要提供了以下几种创建线程池的方法: index method corePoolSize maximumPoolSize ...
  • 我们都知道,Java是一门面向...又是如何被回收的,什么情况下才会被回收等等,今天主要跟大家分享一下:Java中创建对象的几种方式Java中创建对象的几种方式Java中创建对象的四种方式:采用new关键字通过反射采用clon...
  • 创建线程有几种方式呢?? 1、其实,创建线程在本质上只有**两种方式** 继承thread 实现Runnable接口 ①通过Thread创建线程 public class ThreadStyle extends Thread{ @Override public void run(){ System...
  • Java面试题:创建线程有几种方式

    千次阅读 2019-04-17 20:10:09
    小伙子,说下Java创建线程有几种方法? 我: 一般情况下就是继承Thread和实现Runnable接口。这两者之间的区别就是实现Runnable接口,可以避免了继承Thread的单继承局限性。 下面是我总结的一些创建线程的方式 ...
  • 创建线程的四种方式及区别1. 继承Thread2. 实现Runnable接口3. 实现Callable接口4. 线程池方式 1. 继承Thread 一般步骤: 定义Thread的子类,并重写该的run()方法,该run()方法的方法体就代表了线程需要...
  • 创建线程的几种方式

    2019-08-14 11:52:14
    java中创建线程种方式: 1)继承Thread类创建线程 2)实现Runnable接口创建线程 3)使用Callable和Future创建线程 4)使用线程池例如用Executor框架 下面让我们分别来看看这四种创建线程的方法。 --------------...
  • java 中创建线程几种方式? Java中创建线程主要三种方式: 一、继承Thread类创建线程 (1)定义Thread的子类,并重写该的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()...
  • 创建Servlet的几种方式

    2020-04-23 14:09:44
    创建Servlet多种方式创建一个普通的去实现Servlet接口,重写该接口中未实现的方法 继承JAVA中提供的GenericServlet,该已经实现了Servlet,ServletConfig和Serializable接口 继承HttpServlet,该是...
  • 4种方式可以用来创建线程: 继承Thread 实现Runnable接口 应用程序可以使用Executor框架来创建线程池 实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread。在应用设计中已经继承了别的对象的情况下,...
  • 继承Thread类创建线程 定义Thread的子类,并重写该的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。 创建Thread子类的实例,即创建了线程对象。 调用线程对象的start()...
  • 创建线程种方式  继承Thread  实现Runnable接口  实现Runnalble接口这种方式更受欢迎,因为这不需要继承Thread。在应用设计中已经继承了别的对象的情况下,这需要多继承(而java不支持多继承),只能...
  • 由于java是一种面向对象的语言,万事...在之前被问过创建对象有几种方式,当时就回答了有一种,用new关键字创建,这是最常见的方式,不管是谁都可以答出。 其实创建对象的方式有四种: 用new关键字创建调用对象...
  • 这个问题一般会出现在面试当中,多线程创建有几种方式呢? 答: 继承Thread类创建线程 通过Runnable接口创建线程 通过Callable和Future创建线程 一、继承Thread类创建线程 (1)定义Thread的子类,并...
  • 方式可以用来创建线程1)继承Thread2)实现Runnable接口3)应用程序可以适用Executor框架来创建线程池实现了Runnable接口这种方式更受欢迎,因为这不需要继承Thread。在应用设计中已经继承了别的对象的情况下,这...
  • 创建对象的几种方式

    2019-08-15 12:56:17
    创建对象一共种方式,分别是使用new关键字创建、使用对象的clone方法、还可以使用class或者Constructor的newInstance方法通过反射创建对象、还可以通过反序列化,调用ObjectInputStream的readObject方法。...
  • 创建类的对象种方式 一、声明类指针并且new初始化。 类指针的声明也可以不new即初始化为空。说说new和不new的区别吧:  初始化为NULL的类指针可以安全调用不涉及类成员变量的类非虚函数成员函数而不出错,...
  • Java创建对象几种方式? 我: 答:面试官,你好,整体来说可以分为四种,细分可以分为5种,分别为: 手动new 通过构造函数创建 实现超类Object的Cloneable方法 通过反射获取模板对象,再通过Class对象的new...
  • Java中创建线程主要种方式: 继承Thread类创建线程 (1)定义Thread的子类,并重写该的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。 (2)创建Thread子类的实例,...
  • java创建线程的三种方式: 继承Thread类创建线程 通过Runable接口创建线程 通过Callable和FutureTask创建线程 总结下: 实现Runnable和实现Callable接口的方式基本相同,不过是后者执行call()方法返回值。 1...
  • [面试]java创建线程有几种方式

    千次阅读 2017-01-23 21:26:57
    一、继承Thread类创建线程子 1.在这子类中重写run方法,在run方法内写线程任务代码 2.创建该子类实例,即是创建了一个线程实例 3.调用该实例的start方法来启动该线程 二、建一个去实现Runnable接口 1.该...
  • 相信好多小伙伴都在搜索过创建线程的方式,网上给的说法也是什么都说两的、三的、四的、五的...),这些观点肯定让好多小伙伴产生迷惑。那我要说的是:这些答案不能说错,只能说不对。那我凭什么这么说...
  • 一般来说我们比较常用的以下四种方式,下面先介绍它们的使用方法。然后,再说面试中怎样回答面试官的问题比较合适。 1、继承 Thread 通过继承 Thread ,并重写它的 run 方法,我们就可以创建一个线程。 首先...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,090
精华内容 836
关键字:

创建类有几种方式