zoukankan      html  css  js  c++  java
  • 线程实现的方式

    1.继承 Thread 类,Thread的底层用的也是Runnable接口

    package com.opendev.Thread;
    
    import java.util.Map;
    
    public class MyThread extends Thread {
    
        /**
         * 继承Thread方式
         *
         *
         *  继承Thread类,需要覆盖方法 run()方法,
         *  在创建Thread类的子类时需要重写 run(),加入线程所要执行的代即可
         *
         *
         */
    
        private String acceptStr;
    
        public MyThread(String acceptStr) {
            this.acceptStr = acceptStr;
        }
    
    
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println("这个传给我的值:" + acceptStr + ",加上一个变量,看看是什么效果:" + i);
            }
        }
    
    
        public static void main(String[] args) {
            new MyThread("Thread测试").start();
            new MyThread("Thread测试").start();
        }
    }
    View Code

    2.实现 Runnable 接口

    package com.opendev.Thread;
    
    
    public class MyRunable implements Runnable {
    
    
        /**
         * 实现Runnable方式
         * <p>
         * <p>
         * <p>
         * Runnable是可以共享数据的,多个Thread可以同时加载一个Runnable,
         * 当各自Thread获得CPU时间片的时候开始运行Runnable,Runnable里面的资源是被共享的,
         * 所以使用Runnable更加的灵活。PS:需要解决共享之后产生的资源竞争问题
         * <p>
         * <<资源共享,案例 抢火车票>>
         */
    
        private String acceptStr;
    
        public MyRunable(String acceptStr) {
            this.acceptStr = acceptStr;
        }
    
        @Override
        public void run() {
            try {
                // 线程阻塞1秒,此时有异常产生,只能在方法内部消化,无法上抛
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 最终处理结果无法返回
            System.out.println("hello : " + this.acceptStr);
        }
    
        public static void main(String[] args) {
            Runnable runnable = new MyRunable("Runable测试");
            long beginTime = System.currentTimeMillis();
            new Thread(runnable).start();
            long endTime = System.currentTimeMillis();
    
            // endTime 和 beginTime是一样的,线程并不会阻塞主线程
            System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!");
        }
    }
    View Code

    3.实现 Callable 接口,它具有返回值 call , 这个新特性从Java1.5之后才有

    package com.opendev.Thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class MyCallable implements Callable<String> {
    
        /**
         * 实现 Callable 接口的方法
         * @return
         * @throws Exception
         *
         * 介绍:
         *如果你希望任务在完成的能返回一个值,那么可以实现Callable接口而不是Runnable接口。
         *在Java SE5中引入的Callable是一种具有类型参数的泛型,
         *它的参数类型表示的是从方法call()(不是run())中返回的值。
         *
         *
         */
    
        private String acceptStr;
    
        public MyCallable(String acceptStr) {
            this.acceptStr = acceptStr;
        }
    
    
        @Override
        public String call() throws Exception {
            // 任务阻塞1秒,并且增加一些信息返回
            Thread.sleep(1000);
            return this.acceptStr + " 增加一些字符并返回";
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Callable<String> callable = new MyCallable("Callable测试");
            FutureTask<String> task = new FutureTask<String>(callable);
            // 创建线程
            new Thread(task).start();
            long beginTime = System.currentTimeMillis();
            // 调用get()阻塞主线程,反之,线程不会阻塞
            String result = task.get();
            long endTime = System.currentTimeMillis();
            System.out.println("hello : " + result);
    
            // endTime 和 beginTime是不一样的,因为阻塞了主线程
            System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!");
        }
    }
    View Code

    总结:

    Runnable、Thread、Callable总结
    最后再来看看它们三个之间的总结。

    实现Runnable接口相比继承Thread类有如下优势
    1)可以避免由于Java的单继承特性而带来的局限
    2)增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的
    3)适合多个相同程序代码的线程去处理同一资源的情况
    4)线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类

    实现Runnable接口和实现Callable接口的区别
    1)Runnable是自从java1.1就有了,而Callable是1.5之后才加上去的
    2)实现Callable接口的任务线程能返回执行结果,而实现Runnable接口的任务线程不能返回结果
    3)Callable接口的call()方法允许抛出异常,而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛
    4)加入线程池运行,Runnable使用ExecutorService的execute方法,Callable使用submit方法
    注:Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取返回结果,当不调用此方法时,主线程不会阻塞

  • 相关阅读:
    解决Ubuntu19.04无法安装SecureCRT
    gluster学习(二)
    gluster学习(一)
    ansible安装过程遇到的问题
    shell在linux里摇摇晃晃
    ubuntu18.10安装网易云音乐
    MVC Bundle生成的css路径问题
    Vuejs自定义select2指令
    VueJs笔记
    在webAPI的BaseController上使用RoutePrefix
  • 原文地址:https://www.cnblogs.com/cb1186512739/p/12735925.html
Copyright © 2011-2022 走看看