精华内容
下载资源
问答
  • 创建多线程的几种方法
    千次阅读
    2022-04-28 18:28:22

    序言

    1. 多线程

    • c++11中引入了线程类thread,头文件

      #include <thread>
      
    • 创建多线程的方法

      std::thread threadName(函数名, 参数1, 参数2, ...)
      
      std::thread threadName(functionName, leftValueArg, rightValueArg, std::ref(refArg), std::cref(constRefArg));
      

      传参可以传左值、右值、引用使用std::ref、const引用使用std::cref;
      参数先copy或move到std::thread对象,再move给函数

    • 程序至少有一个线程(主线程),一旦创建了std::thread对象也就是在主线程外创建了一个子线程,其立刻开始运行

    2. 多线程的创建

    常见的线程创建方式如下:

    1. 普通函数
    2. 成员函数
    3. 仿函数
    4. lambda函数
    
    • 线程创建方式1:普通函数
    #include <iostream>
    #include <thread>
    
    void Function(int a, int& b)
    {
        a = 2;
        b = 2;
    }
     
    int main()
    {
        int a = 1;
        int b = 1;
        // create sub-thread
        std::thread newThread(Function, a, std::ref(b));
    
        std::cout << a << " " << b << std::endl;
     
        // main thread waiting for sub-thread to finish
        newThread.join();
     
        return 0;
    }
    
    // 编译运行
    g++ --o main main.cpp -pthread
    
    • 线程创建方式2:成员函数
    #include <iostream>
    #include <thread>
    
    class MyClass {
    public:
    	void Function(const int& num)
    	{
    		std::cout << "I am " << num << " yeas old" << std::endl;
    	}
    };
    
    int main()
    {
        MyClass object;
        int num = 29;
    
        // create sub-thread
        std::thread newThread(&MyClass::Function, &object, std::cref(num));
    
        // main thread waiting for sub-thread to finish
        newThread.join();
     
        return 0;
    }
    
    • 线程创建方式3:仿函数
    #include <iostream>
    #include <thread>
    
    class MyClass {
    public:
    	void operator() (int& num)
    	{
    		std::cout << "sub-thread start" << std::endl; 
    		num = 30;
    		std::cout << "sub-thread end" << std::endl; 
    	}
    };
    
    int main()
    {
        std::cout << "main thread start" << std::endl;
        
        MyClass object;
        int num = 29;
    
        std::cout << "num = " << num << std::endl;
        
        // create sub-thread
        std::thread newThread(object, std::ref(num));
        // std::thread newThread(MyClass(), std::ref(num)); 也可
    
        // main thread waiting for sub-thread to finish
        newThread.join();
     
        std::cout << "num = " << num << std::endl;
        std::cout << "main thread end" << std::endl;
        
        return 0;
    }
    
    // 上面的例子,也可如下实现
    ...
    int main()
    {
    	// MyClass object;	// no need to create object
    	std::thread newThread(MyClass(), std::ref(num));
    	...
    }
    
    • 线程创建方式4:匿名函数lambda
    #include <iostream>
    #include <thread>
    
    int main()
    {
        auto function = [](int a) { std::cout << a << '\n'; };
    
        // create sub-thread
        std::thread newThread(function, 10);
    
        newThread.join();
    
        return 0;
    }
    
    // 或以如下方式调用lambda函数
    #include <iostream>
    #include <thread>
    
    int main()
    {
        // create sub-thread
        std::thread newThread([](int a) {std::cout << a << std::endl;}, 10);
    
        newThread.join();
    
        return 0;
    }
    

     


    参考文章:

    多线程与单线程的对比
    线程创建的几种方式
    cpp官网线程创建的几种方式
    ros多线程创建

    created by shuaixio, 2022.04.30

    更多相关内容
  • 如何创建线程创建线程几种方法?怎么实现的?

    多线程有几种实现方法?

    多线程实现又3种方法,其中前两中是常用的方法,推荐第二种方法,一个类应该在其修改或者加强是才继承

    1.继承Thread类,重写run()方法,实例化该类,调用线程start()方法

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

    (2)创建该Thread子类实例

    (3)然后调用线程start()方法


        public class TestThread extends  Thread{
            @Override
            public void run() {
                printThreadMsg("1.2.new TestThread run");
            }
        }
        /**
         * 打印线程信息
         * @param msg
         */
        private void printThreadMsg(String msg)
        {
            System.out.println(msg+":threadName:"+Thread.currentThread().getName()+",threadId:"+Thread.currentThread().getId());
        }

            /**
             * 1.1 匿名内部类(继承Thread类,重写run()方法)
             */
            new Thread(){
                @Override
                public void run() {
                    printThreadMsg("1.1 new Thread() run");
                }
            }.start();
            /**
             * 1.2 继承Thread类,重写run()方法
             */
            new TestThread().start();

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

    具体步骤:

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

    (2)创建Thread子类实例:用实现Runnable接口的对象作为参数实例化个Thread对象

    (3)然后调用线程start()方法

        public class TestRunnable implements  Runnable{
            @Override
            public void run() {
                printThreadMsg("2.2.TestRunnable run");
            }
        }
    

       /**
             * 2.1实现Runnable接口,并实现该接口的run()的方法,然后用实现Runnable接口的对象作为参数实例化Thread对象
             */
            new Thread(new TestRunnable()).start();
    
            /**
             * 2.2实现Runnable接口,并实现该接口的run()的方法,然后用实现Runnable接口的对象作为参数实例化Thread对象
             */
            new Thread(new Runnable() {
                @Override
                public void run() {
                    printThreadMsg("2.2. new Thread.new Runnable run");
                }
            }).start();



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

    (1)自定义类,实现Callable接口,实现call()方法

    (2)实例化ExecutorService 对象,实例化个刚刚自定义类(实现Callable接口)的对象,把它作为参数调用submit()方法

    (3)注意get()方法获取结果会造成阻塞

        public static  class   TestCallable implements Callable{
            @Override
            public Object call() throws Exception {
                /**
                 * 沉睡6秒,模拟耗时操作
                 */
                Thread.sleep(6000);
                System.out.println("3.TestCallable  call:threadName:"+Thread.currentThread().getName()+",threadId:"+Thread.currentThread().getId());
    
                return "这是 TestCallable call 执行完 返回的结果";
            }
        }

          /**
             *实现Callable接口,重写call()方法
             */
            ExecutorService mExecutorService= Executors.newSingleThreadExecutor();
            Future future=mExecutorService.submit(new TestCallable());
            try {
                /**
                 * future.get()用来获取结果,  会造成线程阻塞,直到call()结束
                 * 等待线程结束,并且返回结果
                 * 线程阻塞了
                 */
            String result= String.valueOf(future.get());
            System.out.println("3.TestCallable call return:"+result+","+Thread.currentThread().getName()+",threadId:"+Thread.currentThread().getId());
    
            } catch (Exception e) {
                e.printStackTrace();
            }

    最后附上所有代码

    package com.hex168.demo.therad;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import java.lang.ref.WeakReference;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * author:dz_hexiang on 2017/9/23 13:06
     * email:472482006@qq.com
     * 测试线程创建
     */
    public class ThreadActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_therad);
            /**
             * 1.1 匿名内部类(继承Thread类,重写run()方法)
             */
            new Thread(){
                @Override
                public void run() {
                    printThreadMsg("1.1 new Thread() run");
                }
            }.start();
            /**
             * 1.2 继承Thread类,重写run()方法
             */
            new TestThread().start();
    
            /**
             * 2.1实现Runnable接口,并实现该接口的run()的方法,然后用实现Runnable接口的对象作为参数实例化Thread对象
             */
            new Thread(new TestRunnable()).start();
    
            /**
             * 2.2实现Runnable接口,并实现该接口的run()的方法,然后用实现Runnable接口的对象作为参数实例化Thread对象
             */
            new Thread(new Runnable() {
                @Override
                public void run() {
                    printThreadMsg("2.2. new Thread.new Runnable run");
                }
            }).start();
    
    
            /**
             *实现Callable接口,重写call()方法
             */
            ExecutorService mExecutorService= Executors.newSingleThreadExecutor();
            Future future=mExecutorService.submit(new TestCallable());
            try {
                /**
                 * future.get()用来获取结果,  会造成线程阻塞,直到call()结束
                 * 等待线程结束,并且返回结果
                 * 线程阻塞了
                 */
            String result= String.valueOf(future.get());
            System.out.println("3.TestCallable call return:"+result+","+Thread.currentThread().getName()+",threadId:"+Thread.currentThread().getId());
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            /**
             * handler 及runnable都是在主线程
             */
            handler.post(handlerRunnable);
        }
    
        public class TestThread extends  Thread{
            @Override
            public void run() {
                printThreadMsg("1.2.new TestThread run");
            }
        }
    
        public class TestRunnable implements  Runnable{
            @Override
            public void run() {
                printThreadMsg("2.2.TestRunnable run");
            }
        }
    
        public Runnable handlerRunnable =new Runnable() {
            @Override
            public void run() {
                printThreadMsg("4.handler handlerRunnable run");
            }
        };
    
        /**
         * 打印线程信息
         * @param msg
         */
        private void printThreadMsg(String msg)
        {
            System.out.println(msg+":threadName:"+Thread.currentThread().getName()+",threadId:"+Thread.currentThread().getId());
        }
    
        private MyHandler handler=new MyHandler(this);
        static class MyHandler extends Handler{
            WeakReference<Activity> activityWeakReference;
    
            MyHandler(Activity c)
            {
                activityWeakReference=new WeakReference<Activity>(c);
            }
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
        }
    
        public static  class   TestCallable implements Callable{
            @Override
            public Object call() throws Exception {
                /**
                 * 沉睡6秒,模拟耗时操作
                 */
                Thread.sleep(6000);
                System.out.println("3.TestCallable  call:threadName:"+Thread.currentThread().getName()+",threadId:"+Thread.currentThread().getId());
    
                return "这是 TestCallable call 执行完 返回的结果";
            }
        }
    }
    

    运行结果



    展开全文
  • 创建多线程(8方式)

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

    无论有多少种形式,创建多线程的真正的方法,

    其实只有两种:

             > 继承 Thread 类

            > 实现 Runnable 接口

    其它形式都是这两种方式的变体。

    1、继承 Thread 类

    ①实现方式

    • 第一步:继承 Thread 类
    • 第二步:重写 run() 方法
    • 第三步:创建 Thread 子类对象
    • 第四步:调用 start() 方法启动线程

    ②start() 方法和 run() 方法区别

    调用 run() 方法仅仅只是调用了一个子类中重写的父类方法,并没有真正开启一个新的线程,还是在当前线程运行,也就是 main 线程。

    ③评价

    因为 Java 是单继承的,一个类继承了 Thread 类就不能继承其它类,所以通常不采用这个办法创建多线程。

    2、实现 Runnable 接口

    ①实现 Runnable 接口形式

    public class CreateThread02Impl {
    
        public static void main(String[] args) {
    
            // 第四步:创建实现了 Runnable 接口的类的对象
            MyRunnableThread runnable = new MyRunnableThread();
    
            // 第五步:创建 Thread 类对象
            // 参数1:runnable 对象
            // 参数2:线程名称
            Thread thread = new Thread(runnable, "thread 002");
    
            // 第六步:调用 Thread 对象的 start() 方法启动线程
            thread.start();
        }
    
    }
    
    // 第一步:实现 Runnable 接口
    class MyRunnableThread implements Runnable {
    
        // 第二步:实现 run() 方法
        @Override
        public void run() {
    
            // 第三步:编写线程中的逻辑代码
            System.out.println(Thread.currentThread().getName() + " is working");
        }
    }

    ②匿名内部类形式

    // 第一步:以匿名内部类的方式创建 Runnable 接口类型的对象
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // 第二步:编写线程中的逻辑代码
            System.out.println(Thread.currentThread().getName() + " is working");
        }
    };
    
    // 第三步:创建 Thread 类对象
    // 参数1:runnable 对象
    // 参数2:线程名称
    Thread thread = new Thread(runnable, "thread 003");
    
    // 第四步:调用 Thread 对象的 start() 方法启动线程
    thread.start();

    ③Lambda 表达式形式

    // 编写 Lambda 表达式的口诀:
    // 复制小括号
    // 写死右箭头
    // 落地大括号
    
    // 第一步:以匿名内部类的方式创建 Runnable 接口类型的对象
    Runnable runnable = () -> {
        // 第二步:编写线程中的逻辑代码
        System.out.println(Thread.currentThread().getName() + " is working");
    };
    
    // 第三步:创建 Thread 类对象
    // 参数1:runnable 对象
    // 参数2:线程名称
    Thread thread = new Thread(runnable, "thread 004");
    
    // 第四步:调用 Thread 对象的 start() 方法启动线程
    thread.start();

    3、使用 Callable 接口配合 FutureTask

     在JDK1.5提供了Future和Callable的实现,可以用于阻塞式获取结果

    该方案最核心的价值是:使用 Callable 接口限定的功能 + Future 接口限定的功能 = 汇总各个线程执行结果

    最终执行汇总操作的这一步会被阻塞,直到前面各个线程完成了计算。

    ①FutureTask类和Runnable接口的关系

    从继承关系能够看到,FutureTask本身也间接实现了Runnable接口。FutureTask类的对象也是Runnable接口的实例,可以用于在创建Thread对象时,传入Thread构造器。

    ②Future 接口

    boolean cancel(boolean mayInterruptIfRunning);
    如果尚未启动,它将停止任务。如果已启动,则仅在 mayInterrupt 为 true 时才会中断任务。
    
    V get() throws InterruptedException, ExecutionException;
    如果任务完成,它将立即返回结果,否则将等待任务完成,然后返回结果。
    
    boolean isDone();
    如果任务完成,则返回true,否则返回false。
    

     ③FutureTask 类的构造器

    【1】.介绍:

    FutureTask 类兼具 Runnable 和 Future 接口的功能,并方便地将两种功能组合在一起。关于 FutureTask 类的使用有如下建议:

    • 在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给 Future 对象在后台完成
    • 当主线程将来需要时,就可以通过 Future 对象获得后台作业的计算结果或者执行状态
    • 一般 FutureTask 多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
    • 仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get() 方法
    • 一旦计算完成,就不能再重新开始或取消计算
    • get() 方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常
    • get() 只执行一次,因此get() 方法放到最后

    【2】可以使用的构造器

        public FutureTask(Callable<V> callable) {
            if (callable == null)
                throw new NullPointerException();
            this.callable = callable;
            this.state = NEW;       // ensure visibility of callable
        }

    根据这个构造器,我们知道,创建 FutureTask 对象时,传入一个 Callable 类型的对象即可。

    ④Callable 接口

    @FunctionalInterface
    public interface Callable<V> {
        /**
         * Computes a result, or throws an exception if unable to do so.
         *
         * @return computed result
         * @throws Exception if unable to compute a result
         */
        V call() throws Exception;
    }

    从 call() 方法的声明我们可以看出,它有一个返回值。这个返回值可以将当前线程内计算结果返回。

    ⑤测试代码

    // 1.创建三个FutureTask对象,封装三个线程的执行逻辑
    FutureTask<Integer> task01 = new FutureTask<>(() -> {
    
        int result = (int) (Math.random() * Math.random() * 100);
    
        System.out.println(Thread.currentThread().getName());
    
        return result;
    });
    FutureTask<Integer> task02 = new FutureTask<>(() -> {
    
        int result = (int) (Math.random() * Math.random() * 1000);
    
        System.out.println(Thread.currentThread().getName());
    
        return result;
    });
    FutureTask<Integer> task03 = new FutureTask<>(() -> {
    
        int result = (int) (Math.random() * Math.random() * 10000);
    
        System.out.println(Thread.currentThread().getName());
    
        return result;
    });
    
    // 2.创建三个线程对象,然后启动线程
    new Thread(task01, "thread01").start();
    new Thread(task02, "thread02").start();
    new Thread(task03, "thread03").start();
    
    // 3.上面三个线程执行完成后,可以收集它们各自运算的结果
    Integer task01Result = task01.get();
    Integer task02Result = task02.get();
    Integer task03Result = task03.get();
    
    System.out.println("task01Result = " + task01Result);
    System.out.println("task02Result = " + task02Result);
    System.out.println("task03Result = " + task03Result);

    ⑥Callable和Runnable对比

    Runnable接口

    Callable接口

    重写run()方法

    重写call()方法

    run()没有返回值

    call()有返回值

    run()没有声明抛出异常

    call()声明抛出Exception

    没有汇总各个线程结果的机制

    有汇总各个线程结果的机制

    ⑦Callable接口方案的特点

    该方案仅在具体任务计算完成时才能检索结果;如果计算尚未完成,则阻塞 get() 方法。一旦计算完成,就不能再重新开始或取消计算。get() 方法获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常, 且只计算一次。

    4、线程池

    1.参考代码

    // 1.创建线程池对象
    ExecutorService pool = Executors.newFixedThreadPool(5);
    
    // 2.给线程池对象分配任务,每一个任务是一个线程
    pool.execute(() -> {
        System.out.println(Thread.currentThread().getName() + " " + new Date());
    });
    
    pool.execute(() -> {
        System.out.println(Thread.currentThread().getName() + " " + new Date());
    });
    
    pool.execute(() -> {
        System.out.println(Thread.currentThread().getName() + " " + new Date());
    });

    2.开发建议:

    阿里开发手册中对线程创建的规定:

    结论:实际开发中,建议使用『自定义线程池』的方式创建多线程。在创建自定义线程池时,使用合理的参数。

    5.CompletableFuture

    这个completableFuture是JDK1.8版本新引入的类。下面是这个类。实现了俩接口。本身是个class。这个是Future的实现类。

     

    CompletableFuture提供了四个静态方法用来创建CompletableFuture对象:

    public static CompletableFuture<Void>   runAsync(Runnable runnable)
    public static CompletableFuture<Void>   runAsync(Runnable runnable, Executor executor)
    public static <U> CompletableFuture<U>  supplyAsync(Supplier<U> supplier)
    public static <U> CompletableFuture<U>  supplyAsync(Supplier<U> supplier, Executor executor)

    Asynsc表示异步,而supplyAsyncrunAsync不同在与前者异步返回一个结果,后者是void.第二个函数第二个参数表示是用我们自己创建的线程池,否则采用默认的ForkJoinPool.commonPool()作为它的线程池.其中Supplier是一个函数式接口,代表是一个生成者的意思,传入0个参数,返回一个结果.

    - runAsync方法不支持返回值。

    - supplyAsync可以支持返回值。

     计算完成时回调方法

    public CompletableFuture<T>     whenComplete(BiConsumer<? super T,? super Throwable> action)
    public CompletableFuture<T>     whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
    public CompletableFuture<T>     whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
    public CompletableFuture<T>     exceptionally(Function<Throwable,? extends T> fn)

    whenComplete可以处理正常或异常的计算结果

    exceptionally处理异常情况

    BiConsumer<? super T,? super Throwable>可以定义处理业务

    whenComplete 和 whenCompleteAsync 的区别:

    • whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。

    • whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。

    ==注意:方法不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)==

    线程串行化与并行化方法

    thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值

    public <U> CompletableFuture<U>     thenApply(Function<? super T,? extends U> fn)
    public <U> CompletableFuture<U>     thenApplyAsync(Function<? super T,? extends U> fn)
    public <U> CompletableFuture<U>     thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)

    thenAccept方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。

    public CompletableFuture<Void>  thenAccept(Consumer<? super T> action)
    public CompletableFuture<Void>  thenAcceptAsync(Consumer<? super T> action)
    public CompletableFuture<Void>  thenAcceptAsync(Consumer<? super T> action,
                                                         Executor executor)

    thenRun方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行 thenRun的后续操作

    public CompletableFuture<Void> thenRun(Runnable action)
    public CompletableFuture<Void> thenRunAsync(Runnable action)
    public CompletableFuture<Void> thenRunAsync(Runnable action,
                                                    Executor executor)

    带有Async默认是异步执行的。这里所谓的异步指的是不在当前线程内执行。

    6、并行计算[了解]

    List<String> list = Arrays.asList("a", "b", "c", "d", "e");
    
    // 串行计算
    list.stream().forEach(System.out::print);
    
    System.out.println();
    
    // 并行计算
    list.parallelStream().forEach(System.out::print);

     7、Timer 定时任务[了解]

    // 1、创建 Timer 对象封装定时任务中要执行的操作
    // 每一个 Timer 对象会使用一个线程来执行定时任务
    Timer timer01 = new Timer();
    
    // 2、调用 schedule() 指定任务和执行周期
    // 参数1:timerTask 封装具体任务操作
    // 参数2:delay 指定定时任务延迟多久后开始执行
    // 参数3:period 指定定时任务执行的时间间隔
    timer01.schedule(new TimerTask() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() +" is working");
        }
    }, 0, 1000);
    
    Timer timer02 = new Timer();
    
    timer02.schedule(new TimerTask() {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() +" is working");
        }
    }, 0, 1000);

    8、Spring 异步方法[了解]

    在 Spring 环境下,如果组件 A(假设是 ControllerA)要调用组件 B(假设是 ServiceB)的多个方法,而且希望这些方法能够异步执行。

    [1]开启异步功能

    在主启动类使用 @EnableAsync 注解:

    // 开启支持异步方法调用功能
    @EnableAsync
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
    }

    [2]标记异步方法

    在想要异步调用的方法上使用 @Async 注解:

    @Service
    public class DemoService {
    
        // 在想要实现异步调用的方法上加 @Async注解
        @Async
        public void doSth() {
            System.out.println("Demo Service " + Thread.currentThread().getName());
        }
    
    }

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

    千次阅读 2017-11-29 22:23:00
    多线程几种实现方法,分别是什么?(创建线程的几种方式) 多线程有三种实现方法: 1、继承Thread类,重写run()方法。然后直接new这个对象的实例,创建一个线程的实例,再调用start()方法启动线程...

    多线程有几种实现方法,分别是什么?(创建线程的几种方式)


    多线程有三种实现方法:

    1、继承Thread类,重写run()方法。然后直接new这个对象的实例,创建一个线程的实例,再调用start()方法启动线程。(其实本质上Thread是实现了Runnable接口的一个实例,Thread源文件:public class Thread implements Runnable

    2、实现Runnable接口,重写run()方法。然后调用new Thread(runnable)的方式创建一个线程,再调用start()方法启动线程。

    3、实现Callable接口,重写call()方法。Callable是类似于Runnable的接口,是属于Executor框架中的功能类。是JDK1.5中引入的新特性。(不常用,作为了解引自于

    • Runnable和Callable的不同点:
    •         ①Callable规定的方法是call(),而Runnable规定的方法是run(). 
    •         ②Callable的任务执行后可返回值,而Runnable的任务是不能返回值的(有返回值用callable方法,无返回值用runnable方法
    •         ③call()方法可抛出异常,而run()方法是不能抛出异常的。 
    •         ④运行Callable任务可拿到一个Future对象,Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等
    •         待计算的完成,并检索计算的结果.通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果

    前两种方法的详细分析:

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

    1、定义一个类继承Thread类。

    2、覆盖Thread类中的run方法。


    3、创建一个线程的实例(Thread类的子类对象)。


    4、调用start方法启动线程执行run方法。



    (2)实现Runnable接口,重写run()方法:

    1、定义类实现Runnable接口。


    2、重写接口中的run()方法,将线程的任务代码封装到run()方法中。



    3、通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。

    为什么要进行参数传递?因为线程的任务都封装在Runnable接口子类对象的run方法中,所以要在线程对象创建时就明确要运行的任务。


    4、调用线程对象的start方法开启线程。


    实现Runnable接口的好处,优点:

    1、实现Runnable接口的方法中线程类只是实现了Runnable接口,还可以继承其他的类。避免的java单继承的局限性。

    2、在这种方式下,可以多个线程共享一个Runnable对象,利于资源共享。适合多个相同的线程去处理同一份资源。

    尽量使用实现Runnable接口的方法

    展开全文
  • C++多线程的6种创建方法

    千次阅读 2021-12-12 17:32:33
    创建线程: 包含头文件,调用thread类创建一个线程对象; #include <thread> #include <iostream> using namespace std; void print(){ cout<<"子线程"<<endl; } int main(){ thread ...
  • 若一个进程中同一时间并行执行多个线程,就是支持多线程的。线程作为调度和执行的单位,每个线程都拥有独立的运行栈和程序计数器,一个进程中的多个线程共享相同的内存单元/内存地址空间——>他们从
  • 创建线程几种方式

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

    千次阅读 2020-04-26 21:55:54
    并把需要多线程运行的程序放到 public void run() 方法里。 启动:在主函数中,new 出 MyThread1 类的实例。 运行:调用 MyThread1类的实例的 start() 方法即可。 第二方式: 创建:编写一个类 MyThrea...
  • 作为java程序开发,离不开spring,那么在spring中怎么创建多线程并将注册到spring的类在多线程中使用呢?我自己总结了一下,可以有两方式,使用线程池和spring自带多线程注解使用。 使用线程池 我一般使用固定...
  • 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)...
  • 创建线程几种方式

    千次阅读 2019-04-12 12:07:59
    创建线程几种方式: 方式1:通过继承Thread类创建线程 步骤:1.定义Thread类的子类,并重写该类的run方法,该方法方法体就是线程需要执行的任务,因此run()方法也被称为线程执行体 2.创建Thread子类的实例,...
  • 1 多线程相关概念 并发(Concurrent):在操作系统中,是指一个时间段中有个程序都处于已启动运行到运行完毕之间,且这个程序都是在同一个处理机上运行。 同一时刻只能有一条指令执行,但多个进程指令被快速的...
  • Qt—使用Qt实现多线程设计的四种方法 一、写在前面 ​ 这篇文章内容是:关于Qt多线程应用设计,在Qt中提供了四种方法来进行多线程编程和设计。合理的选择对应的方法来解决实际开发中遇到的开发问题有助于对应用程序...
  • 用Python创建多线程几种方法

    千次阅读 2019-06-01 16:40:48
    经过总结,Python创建多线程主要有如下两种方法: 函数 类 接下来,我们就来揭开多线程的神秘面纱。 学会使用函数创建多线程 在Python3中,Python提供了一个内置模块threading.Thread,可以很方便地让我们创建...
  • 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、pandas是什么? 前言 ...示例:pandas 是基于NumPy 的一工具,该工具是为了解决数据分析任务而创建的。 ...
  • 实现多线程几种方式

    千次阅读 2021-10-14 18:00:36
    2:重写run()方法 3:在测试类中创建ThreadDemo类的对象 4:启动线程 ThreadDemo类 public class ThreadDemo extends Thread { @Override public void run() { for (int i = 0; i <100 ; i++) { System.out....
  • 多线程几种实现方式

    万次阅读 2020-08-02 18:08:57
    1.使用实现多线程有四方式:①继承Thread类;②实现Runnable接口;③使用Callable和FutureTask实现有返回值的多线程;④使用ExecutorService和Executors工具类实现线程池(如果需要线程的返回值,需要在线程中实现...
  • 线程创建的四方式

    千次阅读 2021-05-16 22:43:19
    java中创建线程的四种方法以及区别 Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用四种方式来创建线程,如下所示: 1)继承Thread类创建线程 2)实现Runnable接口创建线程 ...
  • java创建多线程的四方式及其区别

    千次阅读 2019-04-26 18:35:25
    java创建多线程有如下四方式: 继承Thread类创建线程 实现Runnable接口创建线程 使用Callable和Future创建线程 使用线程池创建(使用java.util.concurrent.Executor接口) 下面分别介绍这四种创建多线程的方式...
  • 线程几种创建方式

    千次阅读 2022-03-01 15:03:28
    今天突然用到线程池,就复习下线程这块,记录下工作中常用的知识
  • java有以下四种创建多线程的方式: 1:继承Thread类创建线程 2:实现Runnable接口创建线程 3:使用Callable和FutureTask创建线程 4:使用线程池,例如用Executor框架创建线程 DEMO代码: package thread; ...
  • 线程创建常用的四方式

    千次阅读 2021-03-24 16:28:17
    java中创建线程的四种方法以及区别 Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用四种方式来创建线程,如下所示: 1)继承Thread类创建线程 2)实现Runnable接口创建线程 ...
  • 本文带大家了解Java实现多线程的四种方法以及实现多线程的重要注意事项和难点!
  • Qt创建多线程的两种方法

    万次阅读 多人点赞 2017-12-25 15:33:54
    Qt有两种多线程的方法,其中一种是继承QThread的run函数,另外一种是把一个继承于QObject的类转移到一个Thread里。 Qt4.8之前都是使用继承QThread的run这种方法,但是Qt4.8之后,Qt官方建议使用第二种方法。两种方法...
  • 创建线程方式

    千次阅读 2021-05-30 16:00:37
    第一方式:Thread class 继承Thread...//创建线程方法一,继承Thread类,重写run()方法,调用start开启线程 public class TestThread1 extends Thread{ public void run(){ for (int i = 0; i < 20; i++) { S
  • c++创建线程的6种方法

    千次阅读 2021-04-08 17:57:40
    } -------------------------------------------------------------------------------------------------------------- //引申多线程的数据共享 #include class Seeking { public: Seeking(); ~Seeking(); void ...
  • 多线程几种实现方法

    千次阅读 2019-05-03 15:48:32
    Java多线程实现方式主要有四:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。 其中前两方式线程执行...
  • Java创建多线程的8方式

    万次阅读 多人点赞 2018-07-21 21:16:51
    Java创建启动线程的多种方式 1、继承Thread类,重写run()方法 2、实现Runnable接口,重写run() 3、匿名内部类的方式 4、带返回值的线程(实现implements Callable&lt;返回值类型&gt;)————以上3...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 604,814
精华内容 241,925
热门标签
关键字:

创建多线程的几种方法