精华内容
下载资源
问答
  • Java线程实现方式详解(Java基础)

    千次阅读 多人点赞 2020-05-29 18:15:48
    你好我是辰兮,很高兴你能来阅读,本篇为Java基础之多线程实现讲解,基础知识的讲解,相关的更多,面试知识已经提前整理好文章可以阅读学习,希望对初学者帮助。 线程进程基础知识参考: 进程线程的面试问题小...

    你好我是辰兮,很高兴你能来阅读,本篇为Java基础之多线程的实现讲解,基础知识的讲解,相关的更多,面试知识已经提前整理好文章可以阅读学习,希望对初学者有帮助。



    一、文章序言

    创建线程的方式一致为Java面试常见基础问题,基础学习中我们常用前两种方式,下文带大家用代码案例进一步了解相关的知识。

    在这里插入图片描述

    • 常用第二种接口实现,因为实现接口的方式比继承类的方式更灵活,也能减少程序之间的耦合度。

    二、继承Thread类

    继承自Thread类,Thread类是所有线程类的父类,实现了对线程的抽取和封装

    继承Thread类创建并启动多线程的步骤:

    • ①.定义一个类,继承自Thread类,并重写该类的run方法,该run方法的方法体就代表了线程需要完成的任务,因此,run方法的方法体被称为线程执行体
    • ②.创建Thread子类的对象,即创建了子线程
    • ③.用线程对象的start方法来启动该线程

    Demo先创建一个售票线程

    package demo1;
    
    public class SellTickets extends Thread {
        //共享数据
        static int count = 100;
        @Override
        public void run() {
            //循环售票
            while(count > 0) {
                count--;
                System.out.println(Thread.currentThread().getName() + "售出了一张票,剩余" + count);
            }
        }
    }
    

    测试类

    import demo1.SellTickets;
    
    public class TheadDemo {
    
        public  static void main(String[] args) {
            //模拟四个售票员售票
            SellTickets s1 = new SellTickets();
            SellTickets s2 = new SellTickets();
            SellTickets s3 = new SellTickets();
           // System.out.println(s1.currentThread().getName());  //这个线程的名称是main
            s1.start();
            s2.start();
            s3.start();
    
        }
    }
    

    在这里插入图片描述


    三、实现Runnable接口

    实现Runnable接口创建并启动多线程的步骤:

    • a.定义一个Runnable接口的实现类,并重写该接口中的run方法,该run方法的方法体同样是该线程的线程执行 体
    • b.创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
    • c.调用线程对象的start方法来启动该线程

    • 继续售票的案例 应该是继承implement接口,为了简洁我写一个里面了
    package demo1;
    
    public class SellTickets {
        static int count = 100;
        static Runnable r = new Runnable() {
          @Override
          public void run() {
              while(count > 0) {
                  count--;
                  System.out.println(Thread.currentThread().getName() + "售出了 一张票,剩余" + count);
              }
          }
      };
    
        public static void main(String[] args) {
            Thread t1 = new Thread(r);
            Thread t2 = new Thread(r);
            Thread t3 = new Thread(r);
            t1.start();
            t2.start();
            t3.start();
          }
    }
    

    在这里插入图片描述


    四、两种实现方式的比较

    ①实现Runnable接口的方式

    a.线程类只是实现了Runnable接口,还可以继承其他类【一个类在实现接口的同时还可以继承另外一个类】
    b.可以多个线程共享同一个target对象,所以非常适合多个线程来处理同一份资源的情况
    c.弊端:编程稍微复杂,不直观,如果要访问当前线程,必须使用Thread.currentThread()

    ② 继承Thread类的方式

    a.编写简单,如果要访问当前线程,除了可以通过Thread.currentThread()方式之外,还可以使用 super关键字
    b.弊端:因为线程类已经继承了Thread类,则不能再继承其他类【单继承】 实际上大多数的多线程应用都可以采用实现Runnable接口的方式来实现【推荐使用匿名内部类】java类是单知继承的


    五、调用start()与run()方法的区别

    Thread thread = new Thread();
    thread.start();
    

    ① - start()方法会新建一个线程,并且让这个线程执行run()方法。

    Thread thread = new Thread();
    thread.run();
    

    ② - 调用run()也能正常执行。但是,却不能新建一个线程,而是在当前线程中调用run()方法,只是作为一个普通的方法调用。

    我知道这样表达有点抽象,所有我截图了上述案例

    在这里插入图片描述

    在这里插入图片描述

    建议:不要用run()来开启新线程,它只会在当前线程中,串行执行run()方法中的代码。


    拓展一下源码的学习只截取了部分

    public synchronized void start() {
    
        private native void start0();
    
        /**
         * If this thread was constructed using a separate
         * <code>Runnable</code> run object, then that
         * <code>Runnable</code> object's <code>run</code> method is called;
         * otherwise, this method does nothing and returns.
         * <p>
         * Subclasses of <code>Thread</code> should override this method.
         *
         * @see     #start()
         * @see     #stop()
         * @see     #Thread(ThreadGroup, Runnable, String)
         */
        @Override
        public void run() {
            if (target != null) {
                target.run();
            }
        }
    
    
    }
    

    在start方法里调用了一次start0方法,这个方法是一个只声明未定义的方法,并且使用了native关键字进行定义native指的是调用本机的原生系统函数。所以,调用start方法,会告诉JVM去分配本机系统的资源,才能实现多线程。


    The best investment is to invest in yourself

    在这里插入图片描述

    2020.05.29 记录辰兮的第70篇博客

    展开全文
  • java线程同步的实现方式

    万次阅读 2019-03-08 01:47:21
    这里抛砖引玉,为何要使用同步?...下面总结一些java线程实现同步方式,大致下面几种: 1.同步方法 使用 synchronized关键字,可以修饰普通方法、静态方法,以及语句块。由于java的每个对象都一个内置锁...

    这里抛砖引玉,为何要使用同步?

    当多个线程同时操作一个可共享的资源时会出现线程安全问题,将会导致数据不一致,因此使用同步锁来防止该操作执行完之前不许被其他线程执行,从而保证了该变量的唯一性和准确性。下面总结一些java线程实现同步方式,大致有下面几种:

    1.同步方法 
        使用 synchronized关键字,可以修饰普通方法、静态方法,以及语句块。由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。需要注意的是调用静态方法时,锁住的不是对象,锁住的是类。

     //修饰普通方法
     public synchronized void add(){}
    
     //修饰语句块
     synchronized(object){ 
        
     }
     //修饰静态方法
     public static synchronized int increase(){
    
     }

    同步是一种高开销的操作,因此应该尽量减少同步的内容。 通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。 
          
    2.使用特殊域变量(volatile)实现线程同步

    • volatile关键字为域变量的访问提供了一种免锁机制, 
    • 使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新, 
    • 因此每次使用该域就要重新计算,而不是使用寄存器中的值 
    • volatile不会提供任何原子操作,它也不能用来修饰final类型的变量 

        多线程中的非同步问题主要出现在对域的读写上,如果让域自身避免这个问题,则就不需要修改操作该域的方法。 
        用final域,有锁保护的域和volatile域可以避免非同步的问题。 
        
    3.使用重入锁实现线程同步

        在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。 ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 
        它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。
        ReenreantLock类的常用方法有:

    •  ReentrantLock() : 创建一个ReentrantLock实例 
    •  lock() : 获得锁 
    •  unlock() : 释放锁 

     ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用 
       关于Lock对象和synchronized关键字的选择: 
            a.最好两个都不用,使用一种java.util.concurrent包提供的机制, 
                能够帮助用户处理所有与锁相关的代码。 
            b.如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码 
            c.如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁 
            
    4.使用局部变量实现线程同步 
           如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本, 副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。

       ThreadLocal 类的常用方法

    •     ThreadLocal() : 创建一个线程本地变量 
    •     get() : 返回此线程局部变量的当前线程副本中的值 
    •     initialValue() : 返回此线程局部变量的当前线程的"初始值" 
    •     set(T value) : 将此线程局部变量的当前线程副本中的值设置为value

        ThreadLocal与同步机制 
            a.ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题。 
            b.前者采用以"空间换时间"的方法,后者采用以"时间换空间"的方式

    5.使用阻塞队列实现线程同步

    上面的实现方式都是在底层实现的线程同步,但是我们在实际开发当中,应当尽量远离底层结构。 使用javaSE5.0版本中新增的java.util.concurrent包将有助于简化开发。 例如使用LinkedBlockingQueue<E>来实现线程的同步 。
        LinkedBlockingQueue<E>是一个基于已连接节点的,范围任意的blocking queue。 
        队列是先进先出的顺序(FIFO),关于队列以后会详细讲解~ 
        LinkedBlockingQueue 类常用方法 
        LinkedBlockingQueue() : 创建一个容量为Integer.MAX_VALUE的LinkedBlockingQueue 
        put(E e) : 在队尾添加一个元素,如果队列满则阻塞 
        size() : 返回队列中的元素个数 
        take() : 移除并返回队头元素,如果队列空则阻塞

    BlockingQueue<E>定义了阻塞队列的常用方法,尤其是三种添加元素的方法,我们要多加注意,当队列满时:

     

    • add()方法会抛出异常
    • offer()方法返回false
    • put()方法会阻塞

    6.使用原子变量实现线程同步
         原子操作就是指将读取变量值、修改变量值、保存变量值看成一个整体来操作,即-这几种行为要么同时完成,要么都不完成。在java的util.concurrent.atomic包中提供了创建了原子类型变量的工具类,使用该类可以简化线程同步。其中AtomicInteger 表可以用原子方式更新int的值,可用在应用程序中(如以原子方式增加的计数器),但不能用于替换Integer;可扩展Number,允许那些处理机遇数字类的工具和实用工具进行统一访问。
    AtomicInteger类常用方法:

    • AtomicInteger(int initialValue) : 创建具有给定初始值的新的AtomicInteger
    • addAddGet(int dalta) : 以原子方式将给定值与当前值相加
    • get() : 获取当前值

    代码实例:

     

     1 class Bank {
     2         private AtomicInteger account = new AtomicInteger(100);
     3 
     4         public AtomicInteger getAccount() {
     5             return account;
     6         }
     7 
     8         public void save(int money) {
     9             account.addAndGet(money);
    10         }
    11 } 

     

    补充--原子操作主要有:
      对于引用变量和大多数原始变量(long和double除外)的读写操作;
      对于所有使用volatile修饰的变量(包括long和double)的读写操作。

    展开全文
  • java实现线程通信的几种方式

    万次阅读 2020-05-30 19:34:35
    前言 在多线程的世界里,线程线程之间的交互无处不在,只不过...1、synchronized实现方式 可能很多小伙伴们会疑问,synchronized是对共享资源加锁使用的,怎么和线程通信扯在一起呢?这里纠正一个小小的偏见,也是

    前言

    在多线程的世界里,线程与线程之间的交互无处不在,只不过在平时的开发过程中,大多数情况下,我们都在单线程的模式下进行编码,即使有,也直接借助框架自身的机制实现了,其实线程之间的通信在JDK中是一个比较深的问题,比如大家熟知的消息中间件的实现,从某种角度上讲,就借助了多线程通信的思想,下面总结了JDK中常用的几种实现线程通信的方式,提供参考

    1、synchronized实现方式

    可能很多小伙伴们会有疑问,synchronized是对共享资源加锁使用的,怎么和线程通信扯在一起呢?这里纠正一个小小的偏见,也是我近期才矫正过来的

    我们要弄明白的一点是,为什么会存在线程通讯这个问题呢?根据一些技术大牛们的说法就是,多个线程之间需要相互传递一些参数、变量或者是各个线程的执行需要互相依赖各自的结果,比如我们熟知的生产者消费者模式,只有生产者生产出来了东西,消费者才能进行消费啊

    这里模拟假如有2个线程,需要操作一个共享资源,即修改共享资源的数据,使用synchronized的方式如下:

    public class SycDemo1 {
    
        private static Object lock = new Object();
    
        private static String weather = "sunny";
    
        public static void main(String[] args) {
    
            new Thread(()->{
                synchronized (lock){
                    System.out.println("
    展开全文
  • Java线程的4种实现方式

    万次阅读 2019-04-12 07:48:57
    Java线程的4种实现方式 1:继承Thread并重写run方法,并调用start方法 /** * Java实现多线程的方式1 * 继承Thread类,重写run方法 * @author hongbo.zhao 2019年4月12日 上午7:12:35 */ class MyThread ...

    **

    Java多线程的4种实现方式

    **

    1:继承Thread并重写run方法,并调用start方法

    /**
     * Java实现多线程的方式1
     * 继承Thread类,重写run方法
     * @author hongbo.zhao 2019年4月12日 上午7:12:35
     */
    class MyThread extends Thread {
    	
    	@Override
    	public void run() {
    		//此处为thread执行的任务内容
    		System.out.println(Thread.currentThread().getName());
    	}
    }
    
    public class Demo03 {
    	
    	
    	public static void main(String[] args) {
    		
    		for(int i=0;i<2;i++) {
    			Thread t = new MyThread();
    			//输出:
    			//Thread-0 Thread-1
    			t.start();
    		}
    	}
    }
    

    2:实现Runnable接口,并用其初始化Thread,然后创建Thread实例,并调用start方法

    /**
     * Java实现多线程的方式2
     * 实现Runnable接口
     * @author hongbo.zhao 2019年4月12日 上午7:12:35
     */
    class MyThread implements Runnable {
    	
    	@Override
    	public void run() {
    		//此处为thread执行的任务内容
    		System.out.println(Thread.currentThread().getName());
    	}
    }
    
    public class Demo03 {
    	
    	
    	public static void main(String[] args) {
    		
    		for(int i=0;i<2;i++) {
    			Thread t = new Thread(new MyThread());
    			//输出:
    			//Thread-0 Thread-1
    			t.start();
    		}
    	}
    }
    

    3:实现Callable接口,并用其初始化Thread,然后创建Thread实例,并调用start方法

    
    /**
     * Java实现多线程的方式3
     * 实现Callable接口
     * @author hongbo.zhao 2019年4月12日 上午7:12:35
     */
    class MyThread implements Callable<Integer> {
    	
    	@Override
    	public Integer call() throws Exception {
    		System.out.println(Thread.currentThread().getName());
    		return null;
    	}
    }
    
    public class Demo03 {
    	
    	
    	public static void main(String[] args) {
    		
    		for(int i=0;i<2;i++) {
    			//创建MyThread实例
    			Callable<Integer> c = new MyThread();
    			//获取FutureTask
    			FutureTask<Integer> ft = new FutureTask<Integer>(c);
    			//使用FutureTask初始化Thread
    			Thread t = new Thread(ft);
    			//输出:
    			//Thread-0 Thread-1
    			t.start();
    		}
    	}
    }
    

    4:使用线程池创建

    
    /**
     * Java实现多线程的方式4
     * 线程池
     * @author hongbo.zhao 2019年4月12日 上午7:12:35
     */
    class MyThread implements Runnable {
    
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName());
    	}
    	
    }
    
    class MyThread2 implements Callable<Integer> {
    
    	@Override
    	public Integer call() throws Exception {
    		System.out.println(Thread.currentThread().getName());
    		return 0;
    	}
    
    	
    }
    
    public class Demo03 {
    	
    	
    	public static void main(String[] args) {
    		
    		ExecutorService executorService = Executors.newFixedThreadPool(5);
    		for(int i=0;i<2;i++) {
    			executorService.execute(new MyThread());
    			FutureTask<Integer> ft = new FutureTask<Integer>(new MyThread2());
    			//输出
    //			pool-1-thread-1
    //			pool-1-thread-2
    //			pool-1-thread-3
    //			pool-1-thread-4
    			executorService.submit(ft);
    		}
    		executorService.shutdown();
    	}
    }
    
    展开全文
  • java线程实现的几种方式

    千次阅读 2019-01-29 13:43:30
    1.通过继承Thread类实现 public class MyThread extends Thread{ public void run(){ System.out.println(&amp;amp;quot;New Thread : &amp;amp;quot;+Thread.currentThread().getName()); } public ...
  • java线程编程】三种多线程实现方式

    万次阅读 多人点赞 2019-01-01 16:20:56
    文章目录前言进程与线程继承Thread类,实现线程FAQ 为什么多线程的启动不直接使用run()方法而必须使用Thread类中start()方法呢?...在java语言最大的特点是支持多线程的开发(也是为数不多...
  • Java:简述Java线程的四种实现方式

    千次阅读 2018-06-04 00:12:01
    Java线程实现方式主要四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用线程池接口ExecutorService结合Callable、Future实现返回结果的多线程。 其中前两...
  • java线程实现的四种方式

    千次阅读 2018-08-29 11:13:07
    线程是一个动态执行的过程,它也一个从产生到死亡的过程。 下图显示了一个线程完整的生命周期。 新建状态: 使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持...
  • Java线程实现的四种方式

    万次阅读 多人点赞 2017-07-19 01:45:07
    Java线程实现方式有四种 1.继承Thread类,重写run方法 2.实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target 3.通过Callable和FutureTask创建线程 4.通过线程池创建...
  • JAVA线程实现原理、线程状态

    千次阅读 2018-08-20 14:24:27
    JAVA线程现在的实现是基于操作系统原生线程模型来实现的。因此,现在操作系统支持怎样的线程模型,在很大程度上决定了JAVA虚拟机的线程是怎样映射的。这点在不同的平台上没有办法达成一致。 对于Sun JDK来说,它的...
  • Java线程的4种实现方式详解以及案例演示

    千次阅读 多人点赞 2020-03-11 23:08:55
    介绍了Java线程的4种实现方式:继承Thread、实现Runnable、实现Callable、使用线程池。
  • java实现线程及同步方式

    千次阅读 2018-05-22 14:46:21
    线程实现方式 1)、实现Runnable接口,并实现run()方法 以下是主要步骤: 1、自定义类并实现Runnable接口,并实现run()方法。 2、创建Thread对象,用实现Runnable接口的对象作为参数实例化该Thread对象。 3...
  • java线程的6种实现方式详解

    万次阅读 多人点赞 2017-10-12 12:41:57
    线程的形式上实现方式主要两种,一种是继承Thread类,一种是实现Runnable接口。本质上实现方式都是来实现线程任务,然后启动线程执行线程任务(这里的线程任务实际上就是run方法)。这里所说的6种,实际上都是在...
  • 分享一个大牛的人工智能教程。零基础!通俗易懂!...两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类一个父类,如果继承了Thread类就无法再继...
  • Java线程的底层实现

    千次阅读 2019-06-24 15:14:32
    是操作系统,尽管本文侧重于介绍 Java 线程实现原理,但是请大家清楚一点,实际上实现线程的老大哥,是运行在内核态的操作系统。 Java 语言提供了不同硬件和操作系统平台下对线程操作的统一处理,每个已经执...
  • Java线程实现

    千次阅读 2018-10-13 15:43:25
    java中主要提供两种方式现实多线程,它们需要继承java.lang.Thread类或实现java.lang.Runnable接口。 继承Thread类 程序员启动一个新线程需要建立Thread实例,Thread类中常用的两个构造方法如下: Public ...
  • JAVA线程实现的三种方式

    万次阅读 多人点赞 2014-07-31 18:34:17
    JAVA线程实现方式主要三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。 1、继承...
  • Java线程并发并不一定依赖多线程,但Java里谈论并发大多数都与线程脱不开关系。 线程是比进程更轻量级的调度执行单位,线程的引入可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源(内存地址,...
  • JAVA线程实现的四种方式

    千次阅读 2018-06-19 18:44:40
    Java线程实现方式主要四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现返回结果的多线程。   其中前两种方式...
  • Java线程实现方式主要四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现返回结果的多线程。 1、继承Th...
  • 详述Java实现Callable接口实现线程方式

    万次阅读 多人点赞 2018-07-30 14:59:19
    公司项目忙的晕头转向,终于时间可以看点自己...这里我推荐采用实现接口的方式实现线程,原因两点: 1、Java的设计是单继承的设计,如果采用继承Thread的方式实现线程,则不能继承其他的类。 2、采用接...
  • java实现线程的方法哪几种

    千次阅读 2018-09-21 23:55:25
    实现线程的方法三种: 实现Runnable接口,并实现接口的run()方法 继承Thread类,重写run方法 实现Callable接口,重写call()方法 实现Runnable接口,并实现接口的run()方法 (1)自定义类并实现Runnable接口,...
  • JAVA线程——实现同步

    千次阅读 2018-07-26 17:20:33
    java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 从而保证了...
  • Java线程模型及实现方式

    千次阅读 2019-05-26 15:46:07
    为什么要多线程并发? 并发处理的广泛应用是使得阿姆达尔定律代替摩尔定律成为计算机发展源动力的根本原因,也是人类压榨计算机运算能力的最强有力武器。 阿姆达尔(Amdahl)定律通过系统中并行化与串行化的比重来...
  • Java线程实现复制文件

    千次阅读 2018-09-24 15:55:33
    * 多线程实现文件从一个目录复制到另一个目录 * @param sourceFile:给定源文件路径名 * @param desPath:复制点文件路径 * @return */ 代码实现如下: package com.tulun.thread; import java.io.File; import...
  • JAVA线程实现方式主要三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。 1、继承...
  • 一、在java中怎样实现线程? extends Thread implement Runnable 方法一:继承 Thread 类,覆盖方法 run(),我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可。 下面是一个例子:...
  • java线程间通信的方式

    千次阅读 2020-12-12 20:46:07
    java线程间通信的方式1. 共享变量2. 等待/通知3. 管道流 1. 共享变量 volatile修饰的变量,线程间可见,可使用这种变量作为线程间传递消息的媒介; 延伸出来的,还有redis中的值,数据库中的值,都可以作为线程间...
  • java线程间通讯的几种方式

    万次阅读 多人点赞 2018-11-06 20:28:29
    这里用流在两个线程间通信,但是Java中的Stream是单向的,所以在两个线程中分别建了一个input和output public class PipedDemo { private final PipedInputStream inputStream1 ; private final...
  • java线程实现的两种方式

    千次阅读 2018-04-18 10:39:28
    java自带主要两种实现线程方式。第一种:继承线程类Thread,重新run的方法。第二种:实现接口Runnable,重新run方法。我先不说明他们的区别。先看代码的实现。第一种方式:public class MyThread extends ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,061,482
精华内容 424,592
关键字:

java线程实现方式有

java 订阅