美文网首页干货分享
深度分析——Java线程方式及实例

深度分析——Java线程方式及实例

作者: 小白菜aaa | 来源:发表于2020-09-22 14:43 被阅读0次

    简介

    线程创建方式由继承Thread类,实现Runnable接口,实现Callable接口通过FutureTask包装,通过线程池来创建,所以本文主要介绍Java线程方式。

    继承Thread类
    Thread本质是实现Runnable接口的一个实例。实现如下:

    /**
     - 继承Thread类创建线程
     */
    public class MyThread extends Thread {
    
        /**
         * 重写run()方法来实现自己的业务需求
         */
        @Override
        public void run() {
            //打印线程名称及id
            System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
            System.out.println("启动线程Thread");
        }
    }
    
    
        public static void main(String[] args) {
            //main 方法是一个线程
            System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
            System.out.println("============调用其他线程start============");
            //Thread方法创建线程
            MyThread myThread = new MyThread();
            myThread.start();
            //Runnable方法创建线程
    //        MyRunnable myRunnable = new MyRunnable();
    //        new Thread(myRunnable).start();
            System.out.println("============调用其他线程end==============");
        }
    
    

    实现Runnable接口
    当一个类中已经继承了其他类,还要实现线程,就只能采用实现Runnable接口

    /**
     *  实现Runnable接口创建线程
     */
    public class MyRunnable implements Runnable {
    
        /**
         * 重写run()方法来实现自己的业务需求
         */
        @Override
        public void run() {
            //打印线程名称及id
            System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
            System.out.println("启动线程Runnable");
        }
    }
    
    
        public static void main(String[] args) {
            //main 方法是一个线程
            System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
            System.out.println("============调用其他线程start============");
            //Thread方法创建线程
    //        MyThread myThread = new MyThread();
    //        myThread.start();
            //Runnable方法创建线程
            MyRunnable myRunnable = new MyRunnable();
            new Thread(myRunnable).start();
            System.out.println("============调用其他线程end==============");
        }
    
    

    Callable

    /**
     * 实现Callable接口创建线程
     * @param <String>
     */
    public class MyCallable<String> implements Callable<String> {
    
        /**
         * 重写run()方法来实现自己的业务需求
         * @return
         */
        @Override
        public String call() {
            System.out.println("启动线程callable");
            return (String)"启动线程callable";
        }
    }
    
    
        public static void main(String[] args) {
            //main 方法是一个线程
            System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
            System.out.println("============调用其他线程start============");
            //Thread方法创建线程
    //        MyThread myThread = new MyThread();
    //        myThread.start();
            //Runnable方法创建线程
    //        MyRunnable myRunnable = new MyRunnable();
    //        new Thread(myRunnable).start();
            //Callable方法创建线程
            MyCallable<String> myCallable = new MyCallable<>();
            //由Callable<String>创建一个FutureTask<String>对象:
            FutureTask futureTask = new FutureTask(myCallable);
            //注释:FutureTask<String>是一个包装器,它通过接受Callable<String>来创建,它同时实现了Future和Runnable接口。
            //由FutureTask<String>创建一个String对象:
            Thread thread = new Thread(futureTask);
            thread.start();
            System.out.println("============调用其他线程end==============");
        }
    
    

    通过线程池方式来创建线程

    1. 通过Executors来创建线程池
    import java.util.concurrent.*;
    
    public class MyExecutors {
    
        /**
         * 非自定义注解
         * @param args
         */
        public static void main(String[] args) {
            //1.newSingleThreadExecutor():创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定的顺序来执行;
            //(FIFO,LIFO,优先级)
            ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
            for (int i = 0; i < 5; i++) {
                System.out.println("=================newSingleThreadExecutor()=================");
                //存在返回值;可进行Exception处理
                Future result = singleThreadExecutor.submit(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(Thread.currentThread().getName());
                    }
                });
                //判断该任务是否在完成前取消
                System.out.println("result:" + result.isCancelled());
                singleThreadExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(Thread.currentThread().getName());
                    }
                });
                System.out.println("=================newSingleThreadExecutor()=================");
            }
            // 关闭线程池
            singleThreadExecutor.shutdown();
            //2.newFixedThreadPool(int nThreads):创建定长线程池,控制线程的最大并发数量,超出的线程会在队列中等待;
            //nThreads:线程最大并发数量
            ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
            for (int i = 0; i < 10; i++) {
                System.out.println("=================newFixedThreadPool(5)=================");
                fixedThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(Thread.currentThread().getName());
                    }
                });
                System.out.println("=================newFixedThreadPool(5)=================");
            }
            fixedThreadPool.shutdown();
            //3.newCachedThreadPool():创建一个可缓存线程池,若线程长度超过处理需求,可灵活回收空闲的线程,没有空闲线程,则新建线程
            ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
            for (int i = 0; i < 10; i++) {
                System.out.println("=================newCachedThreadPool()=================");
                cachedThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(Thread.currentThread().getName());
                    }
                });
                System.out.println("=================newCachedThreadPool()=================");
            }
            cachedThreadPool.shutdown();
            //4.newScheduledThreadPool():创建拥有固定线程数量,支持定时线程及周期请任务的线程池
            //schedule参数:3(delay)-从现在开始延迟执行的时间  TimeUnit.SECONDS-延迟参数的时间单位
            ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
            System.out.println("newScheduledThreadPool开始时间:" + System.currentTimeMillis());
            for (int i = 0; i < 5; i++) {
                scheduledExecutorService.schedule(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("newScheduledThreadPool执行时间:" + System.currentTimeMillis() + "--" + Thread.currentThread().getName());
                    }
                }, 3, TimeUnit.SECONDS);
            }
            System.out.println("newScheduledThreadPool结束时间:" + System.currentTimeMillis());
            scheduledExecutorService.shutdown();
            //5.newSingleThreadScheduledExecutor():线程池中存在多个线程时,各个线程不同调度来执行,互不影响;当一个线程遇到阻塞时,其他线程都会收到影响被阻塞,但依旧会按照自身的调度来执行,但是会受到阻塞延迟
            ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
            System.out.println("newSingleThreadScheduledExecutor开始时间:" + System.currentTimeMillis());
            for (int i = 0; i < 5; i++) {
                singleThreadScheduledExecutor.scheduleWithFixedDelay(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("newSingleThreadScheduledExecutor执行时间:" + System.currentTimeMillis() + "--" + Thread.currentThread().getName());
                    }
                }, 0,3, TimeUnit.SECONDS);
            }
            System.out.println("newSingleThreadScheduledExecutor结束时间:" + System.currentTimeMillis());
        }
        singleThreadScheduledExecutor.shutdown();
    }
    
    
    1. 通过ThreadPoolExecutor 来自定义创建线程池
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class MyThreadPoolExecutor {
    
        public static void main(String[] args) {
            //自定义线程池 参数讲解
            /*
            int corePoolSize:核心线程数(不会被回收)
            int maximumPoolSize:最大线程数
            long keepAliveTime:当线程数大于核心时,这是多余空闲线程在终止前等待新任务的最长时间
            TimeUnit : 参数时间单位
            BlockingQueue<Runnable> : 线程的阻塞队列(必须有界)
            ThreadFactory : 产生线程的工厂
            RejectedExecutionHandler : 当线程大于总数(最大线程数 + 阻塞队列)时,将由handler拒绝任务
             */
            ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 20, 60, TimeUnit.SECONDS,
                    new ArrayBlockingQueue<>(100), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
            MyThread myThread = new MyThread();
            for (int i = 0; i < 10; i++) {
                executor.execute(myThread);
            }
            //关闭线程池
            executor.shutdown();
        }
    
    

    注:线程池得创建一般不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,可避免资源耗尽的风险。
    1) newFixedThreadPool和newSingleThreadExecutor: 堆积的请求处理队列可能会耗费非常大的内存
    2)newCachedThreadPool和newScheduledThreadPool: 线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程

    结尾

    本文到这里就结束了,感谢看到最后的朋友,都看到最后了,点个赞再走啊,如有不对之处还请多多指正。

    相关文章

      网友评论

        本文标题:深度分析——Java线程方式及实例

        本文链接:https://www.haomeiwen.com/subject/msrhyktx.html