精华内容
下载资源
问答
  • 线程的创建方式有几种
    千次阅读
    2021-12-15 17:01:36

    前言:我相信创建线程的方式对于所有的java开发程序员来说都不陌生,在面试过程中这个问题也是高频考点。鉴于此,小编用本篇博文来整理几种线程的创建方式,希望对同学们有所帮助~


    一、什么是进程?线程和进程有什么关系?

    进程是程序的一次执行过程,是资源分配的最小单位
    线程是CPU调度的最小单位
    线程是进程的一部分
    一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程

    二、线程如何创建?有几种方式?

    线程的创建有很多种方式,总结下来分为以下几种

    1.继承Thread类

    /**
     * 创建线程的第一种方式:继承Thread类
     */
    public class MyThread01 extends Thread{
        @Override
        public void run() {
                System.out.println(Thread.currentThread().getName() + "正在运行");
        }
    
        public static void main(String[] args) {
           MyThread01 myThread01 = new MyThread01();
            myThread01.start();
       		System.out.println(Thread.currentThread().getName() + "正在运行");
        }
    }
    

    2.实现Runable接口

    需要注意的是,当使用实现Runnable接口的方式创建的线程在线程启动的时候不能直接用实现Runnable接口的实现类调start()方法,而是要当做参数传入Thread类实例,然后调用start()方法进行线程启动,原因就是下面这个Runnable接口的实现类MyThread02 不是线程类。

    /**
     * 创建线程的第二种方式:实现Runnable接口
     */
    public class MyThread02 implements Runnable{
        @Override
        public void run() {
                System.out.println(Thread.currentThread().getName() + "正在运行");
        }
    
        public static void main(String[] args) {
            MyThread02 myThread02 = new MyThread02();
            Thread thread = new Thread(myThread02);
            thread.start();
            System.out.println(Thread.currentThread().getName() + "正在运行");
        }
    }
    

    小知识:其实我们的第一种方式中继承的Thread类在源码中也是实现了Runnable接口哟~

    3.实现Callable接口结合FutureTask

    这种创建线程的方式在实际工作中不用常用,所以在面试过程中也很少有遇到,但是了解一些也是加分项哟。 FutureTask是一个实现Runnable接口的类,FutureTask内部有一个成员变量将callable接口的返回值保存起来,并通过提供get方法获取。

    /**
     * 创建线程的第三种方式:实现Callable接口,结合FutureTask
     */
    public class MyThread03 implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println(Thread.currentThread().getName() + "正在运行");
            return "call() 执行完毕";
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            FutureTask<String> futureTask = new FutureTask<>(new MyThread03());
            Thread thread3 = new Thread(futureTask);
            thread3.start();
            System.out.println(Thread.currentThread().getName() + futureTask.get());
        }
    }
    

    4.使用lambda表达式

    /**
     * 创建线程的第四种方式:使用Lambda表达式
     */
    public class MyThread04 {
        public static void main(String[] args) {
            Thread thread = new Thread(() ->{
                System.out.println(Thread.currentThread().getName() + "正在运行");
            });
            thread.start();
        }
    }
    

    当然也可以简写为这样:

    /**
     * 创建线程的第四种方式:使用Lambda表达式
     */
    public class MyThread04 {
        public static void main(String[] args) {
            new Thread(() ->{
                System.out.println(Thread.currentThread().getName() + "正在运行");
            }).start();
        }
    }
    

    5.使用线程池创建

    这种方式其实是实际工作中使用的最多的一种方式,但同时也是大家在面试回答过程中很容易遗漏的。由于这块东西比较多,小编决定后续单独出一篇文章就行补充总结,敬请期待~

    更多相关内容
  • 创建线程几种方式

    万次阅读 2021-08-23 09:39:14
    Java中创建线程主要种方式: 一、继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。 (2)创建Thread子类的实例...

    Java中创建线程主要有三种方式:

    一、继承Thread类创建线程类

    (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。

    (2)创建Thread子类的实例,即创建了线程对象。

    (3)调用线程对象的start()方法来启动该线程。

    
    public class FirstThreadTest extends Thread {
    
        int i = 0;
    
        //重写run方法,run方法的方法体就是现场执行体
        public void run() {
            for (; i < 100; i++) {
                System.out.println(getName() + "  " + i);
            }
        }
    
        public static void main(String[] args) {
    
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + "  : " + i);
                if (i == 50) {
                    new FirstThreadTest().start();
                    new FirstThreadTest().start();
                }
            }
        }
    }
    

    上述代码中Thread.currentThread()方法返回当前正在执行的线程对象。GetName()方法返回调用该方法的线程的名字。

    二、通过Runnable接口创建线程类

    (1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

    (2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

    (3)调用线程对象的start()方法来启动该线程。

    public class RunnableThreadTest implements Runnable{
            private int i;
            public void run()
            {
                for(i = 0;i <100;i++)
                {
                    System.out.println(Thread.currentThread().getName()+" "+i);
                }
            }
            public static void main(String[] args)
            {
                for(int i = 0;i < 100;i++)
                {
                    System.out.println(Thread.currentThread().getName()+" "+i);
                    if(i==20)
                    {
                        RunnableThreadTest rtt = new RunnableThreadTest();
                        new Thread(rtt,"新线程1").start();
                        new Thread(rtt,"新线程2").start();
                    }
                }
    
            }
    }
    

    三、通过Callable和Future创建线程

    (1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。

    (2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。注释:FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了Future和Runnable接口。

    (3)使用FutureTask对象作为Thread对象的target创建并启动新线程。

    (4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

    package com.nf147.Constroller;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class CallableThreadTest implements Callable<Integer> {
    
    
        public static void main(String[] args) {
            CallableThreadTest ctt = new CallableThreadTest();
            FutureTask<Integer> ft = new FutureTask<>(ctt);
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + " 的循环变量i的值" + i);
                if (i == 20) {
                    new Thread(ft, "有返回值的线程").start();
                }
            }
            try {
                System.out.println("子线程的返回值:" + ft.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
    
        }
    
        @Override
        public Integer call() throws Exception {
            int i = 0;
            for (; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + " " + i);
            }
            return i;
        }
    }
    

    四、创建线程的三种方式的对比

    1.采用实现Runnable、Callable接口的方式创见多线程时,优势是:

    (1)线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。

    (2)在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

    劣势是:

    (1)编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。

    2.使用继承Thread类的方式创建多线程时优势是:

    (1)编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。

    劣势是:

    (1)线程类已经继承了Thread类,所以不能再继承其他父类。

    展开全文
  • 线程几种创建方式

    千次阅读 2022-03-01 15:03:28
    今天突然用到线程池,就复习下线程这块,记录下工作中常用的知识
    创建线程的4钟方式
    * 1.继承Thread类
    * 2.实现Runnable 接口
    * 3.实现Callable 接口 + futureTask (可以拿到返回结果,可以处理异常)
    * 4.线程池

    1.继承Thread类

    public class ThreadTest01 {
    
        //继承Thread类
        public static class Thread01 extends Thread{
            @Override
            public void run() {
                System.out.println("当前线程 -> "+Thread.currentThread().getId());
    
                //模拟业务执行
                int i = 10/2;
    
                System.out.println("运行结果 -> "+i);
            }
        }
    
        public static void main(String[] args) {
            System.out.println("main ...  start...");
                
            Thread01 thread01 = new Thread01();
            thread01.start(); //执行异步
    
            System.out.println("main ...  end...");
    
        }
    }

    结果

     

    2.实现Runnable 接口

    public class ThreadTest01 {
    
        //实现Runnable
        public static class Runnable01 implements Runnable{
            @Override
            public void run() {
                System.out.println("当前线程 -> "+Thread.currentThread().getId());
    
                //模拟业务执行
                int i = 10/2;
    
                System.out.println("运行结果 -> "+i);
            }
        }
    
        public static void main(String[] args) {
            System.out.println("main ...  start...");
    
            Runnable01 runnable01 = new Runnable01();
            new Thread(runnable01).start();//开启异步执行
    
            System.out.println("main ...  end...");
        }
    }

    结果

    3.实现Callable 接口 + futureTask

    public class ThreadTest01 {
    
        //实现Callable接口
        public static class Callable01 implements Callable<Integer> {
    
            @Override
            public Integer call() throws Exception {
                System.out.println("当前线程 -> "+Thread.currentThread().getId());
    
                //模拟业务执行
                int i = 10/2;
                System.out.println("运行结果 -> "+i);
    
                //返回结果
                return i;
            }
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            System.out.println("main ...  start...");
    
            FutureTask task = new FutureTask<>(new Callable01());
            new Thread(task).start(); //开启异步执行
    
            //等待线程执行完成 获取返回结果  阻塞等待
            Integer o = (Integer) task.get();
            System.out.println("返回结果 -> "+o);
    
            System.out.println("main ...  end...");
        }
    }

     结果

     4.线程池 创建线程池的方式

      
    /**
     * 创建线程池的方式  
     * Executors.newCachedThreadPool(); code是0 所有都可回收
     * Executors.newFixedThreadPool();  固定大小 code = max; 都不可回收
     * Executors.newScheduledThreadPool(); 定时任务的线程池
     * Executors.newSingleThreadExecutor(); 单线程的线程池,后台从队列获取任务 挨个执行
     */ 
    
    1.Executors.newFixedThreadPool(10);
    
    
    
    /**
    * 七大参数
    * int corePoolSize,  核心线程数  线程池创建好以后就准备就绪的线程数量 就等待来接收异步任务去执行
    * int maximumPoolSize, 最大线程数量 控制资源并发
    * long keepAliveTime, 存活时间 如果当前线程大于核心线程数量  释放空闲线程(maximumPoolSize-corePoolSize)  只要线程空闲大于指定的keepAliveTime
    * TimeUnit unit, 时间单位
    * BlockingQueue<Runnable> workQueue, 阻塞队列 如果任务有很多就会将目前多的任务放在队列里面 只要有线程空闲了 就会从队列里面取出新的任务继续执行
    * ThreadFactory threadFactory, 线程的创建工厂
    * RejectedExecutionHandler handler 如果队列满了 按照我们指定的拒绝策略拒绝执行任务
    *
    * 工作顺序
    *  1.线程池创建,准备好core数量的核心线程,准备好接受任务
    *  2.core满了,就将再进来的任务放入阻塞队列中,空闲的core就会自己去阻塞队列获取任务执行
    *  3.阻塞队列满了,就直接开新线程执行,最大只能开到max指定的数量
    *  4.max 满了就用RejectedExecutionHandler拒绝任务
    *  5.max 都执行完成,又很多空闲。在指定的时间keepAliveTime以后 释放max- core 这些线程
    *  6.new linkedBlockingDeque<>():默认是Integer 的最大值  内存不够问题
    *  7.  一个线程池 core 7 ; max 20 queue 50  ,100并发进来怎末分配的
    *    7个会立即得到执行,50个会进入队列, 再开13个进行执行, 剩下的30个就使用拒绝策略
    *    如果不想抛弃 还要执行 callerRunsPolicy
    */
    2.ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                    200,
                    10,
                    TimeUnit.SECONDS,
                    new LinkedBlockingDeque<>(100000),
                    Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.AbortPolicy()
      );
    5.线程池 采用Executors 工具类
    public class ThreadTest01 {
        /**
         * 创建线程池 当前系统中 线程池只有一两个  每个异步任务都提交给线程池去执行 控制资源
         * Executors.newCachedThreadPool(); code是0 所有都可回收
         * Executors.newFixedThreadPool();  固定大小 code = max; 都不可回收
         * Executors.newScheduledThreadPool(); 定时任务的线程池
         * Executors.newSingleThreadExecutor(); 单线程的线程池,后台从队列获取任务 挨个执行
         */
        public static ExecutorService executorService = Executors.newFixedThreadPool(10);
    
        //实现Runnable接口
        public static class Runnable01 implements Runnable{
    
            @Override
            public void run() {
                System.out.println("当前线程 -> "+Thread.currentThread().getId());
    
                //模拟业务执行
                int i = 10/2;
    
                System.out.println("运行结果 -> "+i);
            }
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            System.out.println("main ...  start...");
    
            //传入一个Runnable
            executorService.execute(new Runnable01());
    
            System.out.println("main ...  end...");
        }
    }

    结果

     5.线程池 采用原生

    public class ThreadTest01 {
    
        //实现Runnable接口
        public static class Runnable01 implements Runnable{
    
            @Override
            public void run() {
                System.out.println("当前线程 -> "+Thread.currentThread().getId());
    
                //模拟业务执行
                int i = 10/2;
    
                System.out.println("运行结果 -> "+i);
            }
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            System.out.println("main ...  start...");
    
            //传入一个Runnable
            ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                    200,
                    10,
                    TimeUnit.SECONDS,
                    new LinkedBlockingDeque<>(100000),
                    Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.AbortPolicy()
            );
    
            executor.execute(new Runnable01());
            System.out.println("main ...  end...");
        }
    }

    结果

     

    展开全文
  • 创建线程几种方式

    千次阅读 2019-04-12 12:07:59
    创建线程几种方式: 方式1:通过继承Thread类创建线程 步骤:1.定义Thread类的子类,并重写该类的run方法,该方法的方法体就是线程需要执行的任务,因此run()方法也被称为线程执行体 2.创建Thread子类的实例,...

    创建线程的几种方式:
    方式1:通过继承Thread类创建线程
    步骤:1.定义Thread类的子类,并重写该类的run方法,该方法的方法体就是线程需要执行的任务,因此run()方法也被称为线程执行体
    2.创建Thread子类的实例,也就是创建了线程对象
    3.启动线程,即调用线程的start()方法

    在这里插入图片描述
    方式2:通过实现Runnable接口创建线程
    步骤:1.定义Runnable接口的实现类,一样要重写run()方法,和第一种方式一样,这里的run()方法也是线程的执行体
    2.创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread类才是真正的线程对象
    3.依然是通过调用线程对象的start方法来启动线程
    在这里插入图片描述
    方式3:使用Callable和Future来创建线程
    注意:和Runnable接口不一样,Callable接口提供了一个call()方法来作为线程的执行体,call()方法比run()方法功能要更加强大,call()方法可以有返回值,call()方法可以声明抛出异常(前两种如果要抛异常只能通过try,catch来实现)。
    步骤:1.创建Callable接口的实现类,并实现call()方法,然后创建该类的实例
    2.使用Future Task类来包装Callable对象。该FutureTask对象封装了Callable对象的call()方法的返回值
    3.使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口并在重写的run方法中执行call方法)
    4.调用FutureTask对象的get方法来获取线程执行结束后的返回值
    在这里插入图片描述

    方法4:通过线程池来创建线程
    注意:ExecutorService es = Executors.newFixedThreadPool(30);
    ExecutorService es = Executors.newCachedThreadPool();
    FixedThreadPool创建的线程池-》用户可以指定线程池大小,但指定了就不可变
    CachedThreadPool创建的线程池-》线程池大小可变
    在这里插入图片描述
    几种创建线程方式的对比:
    实现Runnable和实现Callable接口方式基本相同,不过是后者执行call方法并且有返回值,而run方法无任何返回值,因此可以把这两种方式归为一种方式与继承Thread类的方式进行对比,差别如下(以实现接口方式为主):
    1.线程只是实现Runnable接口或Callable接口,还可以继承其他类(有点像接口和抽象类的区别,java是单继承的,但可以实现多个接口)
    2.实现接口的方式多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形
    3.如果需要访问当前线程,必须调用Thread.currentThread方法
    4.继承Thread类的线程类不能再继承其他父类(java单继承决定)
    因此,一般推荐采用实现接口的方式来创建线程。

    展开全文
  • 线程创建的四种方式

    千次阅读 2021-05-16 22:43:19
    Java可以用四种方式创建线程,如下所示: 1)继承Thread类创建线程 2)实现Runnable接口创建线程 3)使用Callable和Future创建线程 4)使用线程池例如用Executor框架 下面让我们分别来看看这四种创建线程的...
  • 线程创建常用的四种方式

    千次阅读 2021-03-24 16:28:17
    Java可以用四种方式创建线程,如下所示: 1)继承Thread类创建线程 2)实现Runnable接口创建线程 3)使用Callable和Future创建线程 4)使用线程池例如用Executor框架 下面让我们分别来看看这四种创建线程的...
  • JAVA-创建线程几种方式

    千次阅读 2021-05-02 15:37:32
    创建线程几种方式 1、继承Thread类,重写run方法 class MyThread extends Thread{ @Override public void run() { super.run(); } } public class TestThreadCreat { public static void main(String[] args)...
  • 创建线程有几种方式?3种

    千次阅读 2020-07-20 08:17:10
    实现Runnable接口 public class RunnableDemoTest implements Runnable{ public void run() { System.out.println("实现Runnable开启线程!"); } public static void main(String[] args) { Thread thread = new ...
  • 线程创建几种方式

    千次阅读 2020-04-26 21:55:54
    第一种方式创建:编写一个类 MyThread1 (这里只是小生的自定义命名,方便与代码里名称一致)让它继承 Thread 类, 并把需要多线程运行的程序放到 public void run() 方法里。 启动:在主函数中,new 出 ...
  • C++多线程,多线程创建,std::thread,普通函数/成员函数/仿函数/匿名函数
  • 线程创建方式和区别 1.继承Thread类 (1)创建Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。 (2)创建了Thread子类的实例,即创建了线程对象。...
  • 创建线程的四种方式

    千次阅读 2019-11-21 00:29:29
    1. 线程创建有种方式 2. 继承Thread类 3. 实现Runnable接口 4.实现Callable接口 5.线程池创建线程 1. 线程创建有种方式,分别为: 继承Thread类 实现Runnable接口 实现Callable接口 使用Executor...
  • 线程创建的三种方式及区别

    千次阅读 2021-07-13 11:12:30
    创建方式 1. 继承Thread类 定义Thread类的子类,并重写该类的run方法。 创建Thread子类的实例,即创建线程对象。 调用线程对象的start()方法来启动线程。 package Thread; /* 1.继承Thread类 2.重写run()...
  • 创建线程(8种方式

    千次阅读 2022-03-29 20:21:43
    无论多少种形式,创建线程的真正的方法, 其实只有两种: > 继承 Thread 类 > 实现 Runnable 接口 其它形式都是这两种方式的变体。 1、继承 Thread 类 ①实现方式 第一步:继承 Thread 类 第二步...
  • java 创建线程的三种方式创建线程池的四种方式

    万次阅读 多人点赞 2019-02-23 21:01:44
    java创建线程的三种方式: 继承Thread类创建线程类 实现Runnable接口 通过Callable和Future创建线程 java创建线程池的四种方式: newCachedThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理...
  • java创建线程的三种方式

    千次阅读 2022-06-05 22:10:43
    线程创建的三种方式及其对比
  • JDK1.8 创建线程池几种方式

    万次阅读 多人点赞 2019-05-16 12:48:53
    JDK1.8创建线程池几种方式? newFixedThreadPool 定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程 测试代码...
  • 创建线程种方式

    千次阅读 2021-05-30 16:00:37
    第一种方式:Thread class 继承Thread类(重点) 自定义线程类继承Thread类 重写run()方法,编写线程执行体 创建线程对象,调用start()方法启动线程 //创建线程方法一,继承Thread类,重写run()方法,调用start...
  • System.out.println("实现Runnable开启线程!"); } public static void main(String[] args) { Thread thread = new Thread(new RunnableDemoTest()); thread.start(); } } 3.实现Callable接口 ...
  • 线程的三种创建方式以及区别

    千次阅读 2021-03-07 18:10:39
    这里写目录标题一:创建线程的三种方式1.继承类Thread的方式2.继承Runnable接口方式3.使用Callable接口创建线程4.这三种创建线程的区别 一:创建线程的三种方式 1.继承类Thread的方式 注意:这种创建线程方式不能再...
  • 如何创建线程创建线程有几种方法?怎么实现的?
  • 种方式: ①继承Thread类(真正意义上的线程类),是Runnable接口的实现。 ②实现Runnable接口,并重写里面的run方法。 ③使用Executor框架创建线程池。Executor框架是juc里提供的线程池的实现。调用线程的start...
  • 创建线程的三种方式的对比?

    千次阅读 2022-02-14 08:14:14
    1、采用实现 Runnable、Callable 接口的方式创建线程。 优势是: 线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类。 在这种方式下,多个线程可以共享同一个 target 对象,所以非常适合多...
  • 线程的实现方式有如下三 1)继承Thread类创建线程 重写run方法 2)实现Runnable接口创建线程 3)使用Callable和Future创建线程 重写call方法 通过继承Thread类来创建并启动多线程的一般步骤如下 1. 定义Thread类...
  • 线程的4种创建方式及区别

    千次阅读 2020-08-04 16:32:51
    从 1、继承Thread类 2、实现Runnable接口 3、实现Callable接口 4、创建线程池
  • java创建线程的四种方式

    千次阅读 2022-03-14 11:52:41
    查看Thread类源码可以发现,下面这么一个构造参数,target是线程启动的时候要调用的方法(Runnable接口中个run方法),如果为空,那这个类的运行方法什么都不做 那我们是否可以直接初始化线程,然后调用start方法...
  • 创建线程池的方式有几种

    千次阅读 2022-02-23 11:17:09
    线程池的创建方式,定长线程池,可缓存线程池,窃取线程池,单例线程池,可执行调度任务的线程池,线程池

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 630,267
精华内容 252,106
关键字:

线程的创建方式有几种