多线程实现的几种方式

  • 继承Thread

    优点:

    1. 代码简单,直接操作

    2. 没返回值,继承一个类后无法继承其他的类,拓展性差

      public class ThreadTest  {
          public static void main(String[] args) {
              MyThread myThread=new MyThread();
              myThread.setName("thread1");
              myThread.start();
      
              System.out.println("主线程:"+Thread.currentThread().getName());
          }
      }
      class MyThread extends Thread{
          @Override
          public void run() {
              System.out.println("run");
          }
      }
      
  • 实现Runnable接口

    优点:

    1. 可实现多个接口,可再继承一个类

    2. 无返回值,不能直接启动,需要构造一个Thread实例

      public class RunnableTest {
          public static void main(String[] args) {
              MyRunnable myRunnable=new MyRunnable();
              Thread thread= new Thread(myRunnable);
              thread.start();
          }
      }
      class MyRunnable implements Runnable{
      
          @Override
          public void run() {
              System.out.println("run");
          }
      }
      
  • 匿名内部类

     public static void main(String[] args) {
		              new Thread(()->{
		                  System.out.println("run");
		              },"thread1").start();
		          }
  • Callable和FutureTask方式

    • 创建Callable接口的实现类,实现call方法,结合FutureTask类包装Callable对象,实现多线程
    • 优点:有返回值,扩展性也好
    public class CalAndFuture {
          public static void main(String[] args) throws ExecutionException  {
              MyTask myTask=new MyTask();
              FutureTask<Object> futureTask=new FutureTask<>(myTask);
      
              //futureTask继承了Runnable,可以放在Thread中启动执行
              Thread thread=new Thread(futureTask);
              thread.setName("thread1");
              thread.start();
      
              try {
                  System.out.println(futureTask.get());//获取返回值
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
      
          }
      }
      class MyTask implements Callable<Object>{
      
          @Override
          public Object call() throws Exception {
              System.out.println("callable");
              return "sth";
          }
      }
    
  • 通过线程池创建线程
    自定义Runnable接口,实现run方法,创建线程池,调用execute方法并传入对象

  • 优点
    安全性高,复用线程

    public class Pool {
        public static void main(String[] args) {
            ExecutorService executorService= Executors.newFixedThreadPool(3);
    
            for (int i = 0; i < 10; i++) {
    
            executorService.execute(new ThreadDemo());
            }
            executorService.shutdown();
        }
    }
    class ThreadDemo implements Runnable{
    
        @Override
        public void run() {
            System.out.println("ThreadPool+Runnable");
        }
    }
    

    线程池不允许使用 Executors去创建,而是通过 ThreadPool Executor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险
    说明
    1)FixedThreadPool
    内部使用LinkedBlockingQueue, 默认允许的请求队列长度为 Integer. MAX_VALUE,可能会堆积大量的任务请求,从而导致OOM

    2)CachedThreadPool

    允许的请求队列长度为 Integer. MAX VALUE,可能会创建大量的线程,从而导致OOM

ThreadPoolExecutor executor=new ThreadPoolExecutor(6,30,0L, TimeUnit.MINUTES,new LinkedBlockingDeque<>());
              
      
              for (int i = 0; i < 10; i++) {
      
                  executor.execute(new ThreadDemo());
              }
              executor.shutdown();

线程池详见线程池系列的笔记

  • java8的串行计算
   list.parallelStream().forEach(System.out::print);
  • Spring中的@Async异步方法
发布了75 篇原创文章 · 获赞 13 · 访问量 8369

猜你喜欢

转载自blog.csdn.net/weixin_43696529/article/details/105210727