精华内容
下载资源
问答
  • Java中创建线程的三种方法
    2021-03-14 17:26:25

    一、继承Thread类创建线程类

    (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。

    (2)创建Thread子类的实例,即创建了线程对象。

    (3)调用线程对象的start()方法来启动该线程。

    public class Main {

    public static void main(String[] args) throws Exception {

    myThread th1 = new myThread();

    myThread th2 = new myThread();

    th1.start();

    th2.start();

    }

    }

    class myThread extends Thread {

    public void run() {

    for(int i = 0; i < 5; i++) {

    System.out.println(Thread.currentThread().getName() + "运行 : " + i );

    }

    }

    }

    二、通过Runnable接口创建线程类

    (1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

    (2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

    (3)调用线程对象的start()方法来启动该线程。

    public class Main {

    public static void main(String[] args) throws Exception {

    myThread myth = new myThread();

    Thread th1 = new Thread(myth);

    Thread th2 = new Thread(myth);

    th1.start();

    th2.start();

    }

    }

    class myThread implements Runnable {

    public void run() {

    for(int i = 0; i < 5; i++) {

    System.out.println(Thread.currentThread().getName() + "运行 : " + i );

    }

    }

    }

    三、通过Callable和Future创建线程

    (1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。

    (2)创建实现了Callable接口的实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。

    (3)使用FutureTask对象作为Thread对象的target创建并启动新线程。

    (4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

    package test4;

    import java.util.concurrent.Callable;

    import java.util.concurrent.ExecutionException;

    import java.util.concurrent.FutureTask;

    public class Main {

    public static void main(String[] args) {

    ThreadDemo td = new ThreadDemo();

    // 1.执行Callable方式,需要FutureTask实现类的支持,用于接收运算结果

    FutureTask result = new FutureTask<>(td);

    new Thread(result).start();

    // 2.接收线程运算后的结果

    Integer sum;

    try {

    //等所有线程执行完,获取值,因此FutureTask 可用于 闭锁

    sum = result.get();

    System.out.println("-----------------------------");

    System.out.println(sum);

    } catch (InterruptedException | ExecutionException e) {

    e.printStackTrace();

    }

    }

    }

    class ThreadDemo implements Callable {

    @Override

    public Integer call() throws Exception {

    int sum = 0;

    for (int i = 0; i <= 10; i++) {

    System.out.println(i);

    sum += i;

    }

    return sum;

    }

    }

    更多相关内容
  • Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。
  • java中创建线程的4种方式

    千次阅读 2019-04-25 16:00:23
    java线程创建方式有几种?这种问题在面试经常被问到,你可能心里马上反映出两种方式(实现Runnable、继承Thread),当你把这两种叙述给面试官听后,面试官会觉得你该掌握的知识已经有了,但是仅仅而已。如果你还说...

    写在前面的话

    java线程创建方式有几种?这种问题在面试中经常被问到,你可能心里马上反映出两种方式(实现Runnable、继承Thread),当你把这两种叙述给面试官听后,面试官会觉得你该掌握的知识已经有了,但是仅仅而已。如果你还说了callable与future、线程池,那么面试官就会认为你 知识覆盖面广,对你好感加一!下面首先叙述为什么会出现线程,以及线程在实际生活中的例子,紧接着给出四种创建线程的方式,加以代码进行演示。喜欢博主文章的你,动动你们的小爪子,点赞收藏呗(#^.^#)

    1、线程的知识

    1.1、什么是多线程

    百度百科这样说:多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。好像和没说一样,概念还是不怎么理解。那就举个例子:早上小明起床后,需要完成刷牙、洗脸、烧水、听广播,为了节约时间、提高效率,小明边烧水、边听广播、边刷牙洗脸,这三个任务并行进行,就类似于三个线程。多线程就是同时多个线程同时工作,并发执行任务。

    1.2、为什么会有多线程

    这个问题可以转换为:多线程带来了什么好处与优势。结合《JAVA并发编程实践》总结如下:

    1、发挥多处理器的强大能力

    现在的处理器在频率上的提升空间越来越小,为了增加设备整体的性能,出现了多核多处理器设备。由于线程是cpu调度的基本单位, 当一个程序中只有一个线程时,最多只能在一个CPU上进行运行,其他CPU将处于空闲状态,严重影响多核CPU的性能。因此,如果涉及合理正确的多线程程序,将会充分利用多核CPU性能优势,提高整体设备性能。

    2、建模的简单性

    通过使用线程,可以将复杂并且异步的工作流进一步分解为一组简单并且同步的工作流,每个工作流在一个单独的线程中运行,并在特定的同步位置进行交互。我们可以通过一些现有框架来实现上述目标,例如Servlet和RMI,框架负责解决一些细节问题,例如请求管理、线程创建、负载平衡,并在正确的时候将请求分发给正确的应用程序组件。编写Servlet的开发人员不需要了解多少请求在同一时刻要被处理,也不需要了解套接字的输入流或输出流是否被阻塞,当调用Servlet的service方法来响应Web请求时,可以以同步的方式来处理这个请求,就好像它是一个单线程程序。

    3、异步事件的简化处理

    服务器应用程序在接受多个来自远程客户端的套接字连接请求时,如果为每个连接都分配其各自的线程并且使用同步I/O,那么就会降低这类程序的开发难度。如果某个应用程序对套接字执行读操作而此时还没有数据到来,那么这个读操作将一直阻塞,直到有数据到达。在单线程应用程序中,这不仅意味着在处理请求的过程中将停顿,而且还意味着在这个线程被阻塞期间,对所有请求的处理都将停顿。为了避免这个问题,单线程服务器应用程序必须使用非阻塞I/O,但是这种I/O的复杂性要远远高于同步I/O,并且很容易出错。然而,如果每个请求都拥有自己的处理线程,那么在处理某个请求时发生的阻塞将不会影响其他请求的处理。

    4、响应更灵敏的用户界面

    GUI界面采用多线程,可以同时响应多个按钮,比如在IDEA中,在程序运行时,还可以继续进行程序编写。

    1.3、线程与进程的区别

    进程是操作系统进行资源分配的单元,线程是CPU调度运行的单位;一个进程中可以包含很多线程,线程共享进程的内存等资源;每个进程拥有各自独立的一套变量,相互不影响,而线程则共享数据,会存在线程安全问题。

    1.4、举例说明线程与进程

    为了能够看到本地计算机上的线程信息,下载Process Explorer,解压运行进行查看。

     从上图可以形象的验证,进程与 线程之间的关系。关于Process Explorer的用法,感兴趣的可以自行研究。

    2、java创建线程的四种方式

    2.1、实现Runnable

    通过实现Runnable接口,重写run()方法。然后借助Thread的start()方法开启线程,调用run()方法是不会开启新线程的,只是一次方法调用而已。

    看一下Runnable接口的java代码,发现它只有一个run()方法。

    public interface Runnable {
        /**
         * When an object implementing interface <code>Runnable</code> is used
         * to create a thread, starting the thread causes the object's
         * <code>run</code> method to be called in that separately executing
         * thread.
         * <p>
         * The general contract of the method <code>run</code> is that it may
         * take any action whatsoever.
         *
         * @see     java.lang.Thread#run()
         */
        public abstract void run();
    }

    进行线程编写, 

    public class CreateThreads implements Runnable{
    
        @Override
        public void run() {
            System.out.println("通过实现Runnable接口开启线程~");
        }
    
        public static void main(String[] args) {
            CreateThreads createThreads = new CreateThreads();
            Thread thread = new Thread(createThreads);
            thread.start();
        }
    }

    2.2、继承Thread

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

    public class CreateThreads extends Thread{
    
        @Override
        public void run() {
            System.out.println("通过继承Thread开启线程~");
        }
    
        public static void main(String[] args) {
            CreateThreads createThreads = new CreateThreads();
            Thread thread = new Thread(createThreads);
            thread.start();
        }
    }

    注意:继承Thread类,重写run()方法,其本质上与实现Runnable接口的方式一致,因为Thread类本身就实现了Runnable接口

    public class Thread implements Runnable 。再加上java中多实现,单继承的特点,在选用上述两种方式创建线程时,应该首先考虑第一种(通过实现Runnable接口的方式)。

    2.3、通过Callable、Future

    通过Runnable与Thread的方式创建的线程,是没有返回值的。然而在有些情况下,往往需要其它线程计算得到的结果供给另外线程使用( 例如:计算1+100的值,开启三个线程,一个主线程,两个计算线程,主线程需要获取两个计算线程的结算结果(一个计算线程计算1+2+...+50,另外一个线程计算51+52+..+100),进行相加,从而得到累加结果),这个时候可以采用Runnable与Thread的方式创建的线程,并通过自行编写代码实现结果返回,但是不可避免的会出现黑多错误和性能上的问题。基于此,JUC(java.util.concurrent)提供了解决方案,实现Callable的call()方法(这个类似Runnable接口),使用Future的get()方法进行获取。

    下面首先看一下Callable接口:

    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;
    }

    下面开始使用Callable、与Future创建多线程。创建过程为:1、自定义一个类实现Callable接口,重写call()方法;2、使用JUC包下的ExecutorService生成一个对象,主要使用submit()方法,返回得到Future对象(关于JUC包下的诸如ExecutorService解析使用,请关注博主的后序文章);3、采用Future的get()获取返回值。

    import java.util.concurrent.*;
    
    /**
     * @author wolf
     * @create 2019-04-25    14:53
     * 计算1+...+100的结果,开启三个线程,主线程获取两个子线程计算的结果,一个子线程计算1+...+50,一个子线程计算51+...+100。
     */
    public class CreateThreads implements Callable {
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            //生成具有两个线程的线程池
            ExecutorService executorService = Executors.newFixedThreadPool(2);
            //调用executorService.submit()方法获取Future
            Future<Integer> result1 = executorService.submit(new CreateThreads());
            Future<Integer> result2 = executorService.submit(new SubThread());
            //使用Future的get()方法等待子线程计算完成返回的结果
            int result = result1.get() + result2.get();
            //关闭线程池
            executorService.shutdown();
            //打印结果
            System.out.println(result);
    
        }
    
        //子线程1,用来计算1+...+50
        @Override
        public Object call() throws Exception {
            int count = 0;
            for (int i = 1; i <= 50; i++)
                count = count + i;
            return count;
        }
    }
    
    class SubThread implements Callable {
        //子线程2,用来计算51+...+100
        @Override
        public Object call() throws Exception {
            int count = 0;
            for (int i = 51; i <= 100; i++)
                count = count + i;
            return count;
        }
    }
    

    2.4、通过JUC里面的线程池

    JUC并发包里的 Executors工具类,提供了创建线程池的工厂方法,具体可以参看JDK的API。

    下面就Executors.newFixedThreadPool()说明,这里请移步2.3节的程序,会发现其实2.3节已经使用了Executors.newFixedThreadPool(2)构建线程池。

     

    3、总结

    通过上述叙述,希望对你知识掌握和面试有所帮助。多线程是java中的进阶,这一块还有很多知识点,本文后会继续发布关于多线程博客,旨在介绍java中多线程的框架,介绍JUC包,一起学习共勉。文中有错误的地方,还请留言给予指正,不胜感激~最后,喜欢博主的文章不妨关注点赞收藏哦,方便下次不走错门。

    展开全文
  • 主要介绍了Java创建线程的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了Java创建线程异步执行实现代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 众所周知,我们在创建线程时有四种方法可以用,分别是: 1、继承Thread类创建线程 2、实现Runnable接口创建线程 3、使用Callable和Future创建线程 4、使用线程池创建(使用java.util.concurrent.Executor接口) 其中...

    众所周知,我们在创建线程时有四种方法可以用,分别是:
    1、继承Thread类创建线程
    2、实现Runnable接口创建线程
    3、使用Callable和Future创建线程
    4、使用线程池创建(使用java.util.concurrent.Executor接口)

    其中第一、二中最为简单,我已经在前面线程部分详细解释过,不懂得可以去看看:多线程

    今天我们聊聊其他两种和他们的区别。

    1、使用Callable接口和Future创建线程

    和Runnable接口不一样,Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能要强大,其表现在:

    1>call方法可以有返回值
    
    2>call()方法可以声明抛出异常
    

    Java5提供了Future接口来代表Callable接口里call()方法的返回值,并且为Future接口提供了一个实现类FutureTask,这个实现类既实现了Future接口,还实现了Runnable接口,因此可以作为Thread类的target。

    介绍了相关的概念之后,创建并启动有返回值的线程的步骤如下:

    1】创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例(从java8开始可以直接使用Lambda表达式创建Callable对象)。

    2】使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值

    3】使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口)

    4】调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

    其实现代码如下:

    public class MyThread implements Callable<String>{//Callable是一个泛型接口
     
    	@Override
    	public String call() throws Exception {//返回的类型就是传递过来的V类型
    		for(int i=0;i<10;i++){
    			System.out.println(Thread.currentThread().getName()+" : "+i);
    		}
    		
    		return "Hello Tom";
    	}
    	public static void main(String[] args) throws Exception {
    		MyThread myThread=new MyThread();
    		FutureTask<String> futureTask=new FutureTask<>(myThread);
    		Thread t1=new Thread(futureTask,"线程1");
    		Thread t2=new Thread(futureTask,"线程2");
    		Thread t3=new Thread(futureTask,"线程3");
    		t1.start();
    		t2.start();
    		t3.start();
    		System.out.println(futureTask.get());
    		
    	}
    }
    

    FutureTask非常适合用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。 FutureTask可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务,或者通过cancel取消FutureTask的执行等。

    2、线程池

    java中经常需要用到多线程来处理一些业务,但是我们非常不建议单纯使用继承Thread或者实现Runnable接口的方式来创建线程,那样势必有创建及销毁线程耗费资源、线程上下文切换问题。

    但是,众所周知,线程有五种基本状态,分别是:

    1、NEW(初始化)状态
    实例化一个Thread类对象出来(未执行start()方法前),Thread的状态为NEW。

    2、RUNNABLE(可运行)状态
    调用线程的start()方法,此时线程进入RUNNABLE状态,该状态的线程位于可运行线程池中,等待被操作系统调度,获取CPU的使用权。

    当获得CPU的时间片时,线程进入运行状态,执行程序代码。

    3、BLOCKED(阻塞)状态
    当线程等待获取monitor锁(synchronized)时,线程就会进入BLOCKED状态。

    注意:

    等待获取monitor锁,线程的状态是BLOCKED。

    等待获取Lock锁(LockSupport.park()),线程的状态是WAITING。

    4、TIMED_WAITING(超时等待)状态
    当执行

    Thread.sleep(time)
    Thread.join(time)
    Object.wait(time)
    LockSupport.parkNanos(time)
    LockSupport.partUntil(time)
    

    等操作时,线程会从RUNNABLE状态进入TIMED_WAITING状态。

    当执行超时时间到

    Thread.join() 线程执行完
    Object.notify()
    notifyAll()
    LockSupport.unpark()
    

    线程被中断等操作时,线程会从TIMED_WAITING状态进入RUNNABLE状态。

    5、WAITING(等待)状态
    当执行Object.wait()、Thread.join()、LockSupport.park()等操作时,线程会从RUNNABLE状态进入WAITING状态。

    当执行Object.notify()/notifyAll()、Thread.join()程序执行完、LockSupport.unpark()、线程被中断等操作时,线程会从WAITING状态进入RUNNABLE状态。

    6、TERMINATED(终止)状态
    当线程执行完毕、Thread.stop()、内存溢出时,线程就会进入TERMINATED状态。

    线程一旦死亡,就无法复活。
    在一个死亡的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。

    分别对应操作系统进程(线程)的五种状态:
    在这里插入图片描述

    Thread类中有一个内部枚举类描述这六种状态:

    public enum State {
            NEW,
            RUNNABLE,
            BLOCKED,
            WAITING,
            TIMED_WAITING,
            TERMINATED;
        }
    

    所以可想而知,一个线程从创建到使用需要多少时间,又多么麻烦。

    所以上述的三种创建线程的方法,我们现在几乎不考虑,因为有更方便和安全的。

    有没有一种方法将这些繁琐的过程简单化呢?
    有!那就是线程池,创建过多的线程也可能引发资源耗尽的风险,这个时候引入线程池比较合理,方便线程任务的管理。
    java中涉及到线程池的相关类均在jdk1.5开始的java.util.concurrent包中,涉及到的几个核心类及接口包括:Executor、Executors、ExecutorService、ThreadPoolExecutor、FutureTask、Callable、Runnable等。

    再看线程池之前,我们先看两段代码:

    public class PuTongXianCheng {
        public static void main(String[] args) throws Exception {
           	//计时
            Long start = System.currentTimeMillis();
    		//生成随机数
            Random random = new Random();
            List list = new ArrayList();
    
            for (int i = 0;i <= 100000;i++){
            	
                Thread thread = new Thread(){
                	//创建线程
                    @Override
                    public void run() {
                        list.add(random.nextInt());
                    }
                };
                //线程运行
                thread.start();
                thread.join();
            }
            System.out.println("时间:"+(System.currentTimeMillis() - start));
            System.out.println("list = "+list.size());
        }
    }
    
    

    这段代码的运行时间为:
    在这里插入图片描述

    public static void main(String[] args) throws Exception {
            Long start = System.currentTimeMillis();
    
            Random random = new Random();
            List list = new ArrayList();
    
            //创建线程池
            ExecutorService service = Executors.newSingleThreadExecutor();
            for (int i = 0;i <= 100000;i++){
                service.execute(
                        new Thread(){
                            @Override
                            public void run() {
                                list.add(random.nextInt());
                            }
                        }
                );
            }
            service.shutdown();
            service.awaitTermination(1, TimeUnit.DAYS);
    
            System.out.println("时间:"+(System.currentTimeMillis() - start));
            System.out.println("list = "+list.size());
        }
    

    这段代码的运行时间为:
    在这里插入图片描述
    由此可见,线程池比普通线程优越多少,接下来我们学习创建他。

    2.1、线程池的创建

    线程池可以自动创建也可以手动创建:

    1、自动创建体现在Executors工具类中,常见的可以创建newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor,对于这三种线程池,日后我会写博客仔细说。

    public static ExecutorService newFixedThreadPool(int var0) {
            return new ThreadPoolExecutor(var0, var0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
      }
    	
      public static ExecutorService newSingleThreadExecutor() {
            return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));
      }
     
      public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());
      }
    

    2、手动创建主要用ThreadPoolExecutor类,体现在可以灵活设置线程池的各个参数,体现在代码中即ThreadPoolExecutor类构造器上各个实参的不同:

    public ThreadPoolExecutor(int corePoolSize,
                               int maximumPoolSize,
                               long keepAliveTime,
                               TimeUnit unit,
                               BlockingQueue<Runnable> workQueue,
                               ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) 
    

    2.2、ThreadPoolExecutor中重要的几个参数详解

    corePoolSize:核心线程数,也是线程池中常驻的线程数,线程池初始化时默认是没有线程的,当任务来临时才开始创建线程去执行任务。

    maximumPoolSize:最大线程数,在核心线程数的基础上可能会额外增加一些非核心线程,需要注意的是只有当workQueue队列填满时才会创建多于corePoolSize的线程(线程池总线程数不超过maxPoolSize)

    keepAliveTime:非核心线程的空闲时间超过keepAliveTime就会被自动终止回收掉,注意当corePoolSize=maxPoolSize时,keepAliveTime参数也就不起作用了(因为不存在非核心线程);

    unit:keepAliveTime的时间单位

    workQueue:用于保存任务的队列,可以为无界、有界、同步移交三种队列类型之一,当池子里的工作线程数大于corePoolSize时,这时新进来的任务会被放到队列中

    threadFactory:创建线程的工厂类,默认使用Executors.defaultThreadFactory(),也可以使用guava库的ThreadFactoryBuilder来创建。

    handler:线程池无法继续接收任务(队列已满且线程数达到maximunPoolSize)时的饱和策略,取值有AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy。

    2.3、线程池中的线程创建流程

    在这里插入图片描述

    2.4、线程池的拒绝策略

    在此之间,我们需要知道一个前提,所有拒绝策略都实现了接口 RejectedExecutionHandler

    public interface RejectedExecutionHandler {
    
        /**
         * @param r the runnable task requested to be executed
         * @param executor the executor attempting to execute this task
         * @throws RejectedExecutionException if there is no remedy
         */
        void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
    }
    

    这个接口只有一个 rejectedExecution 方法。r 为待执行任务;executor 为线程池;方法可能会抛出拒绝异常。

    当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize时,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

    2.4.1、ThreadPoolExecutor.AbortPolicy

    丢弃任务并抛出RejectedExecutionException异常,也是线程池的默认拒绝策略。

    private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
    

    如果是比较关键的业务,推荐使用此拒绝策略,这样子在系统不能承载更大的并发量的时候,能够及时的通过异常发现。但是会中断调用者的处理过程,所以除非有明确需求,一般不推荐。

    2.4.2、ThreadPoolExecutor.DiscardPolicy

    丢弃任务,但是不抛出异常,如果线程队列已满,则后续提交的任务都会被丢弃,且是静默丢弃。
    使用此策略,可能会使我们无法发现系统的异常状态。建议是一些无关紧要的业务采用此策略。

    2.4.3、ThreadPoolExecutor.DiscardOldestPolicy

    丢弃队列最前面的任务,然后重新提交被拒绝的任务。
    此拒绝策略,是一种喜新厌旧的拒绝策略。是否要采用此种拒绝策略,还得根据实际业务是否允许丢弃老任务来认真衡量。

    2.4.4、ThreadPoolExecutor.CallerRunsPolicy

    由调用线程(提交任务的线程)处理该任务

    3、四种创建线程方法对比

    实现Runnable和实现Callable接口的方式基本相同,不过是后者执行call()方法有返回值,后者线程执行体run()方法无返回值,并且如果使用FutureTask类的话,只执行一次Callable任务。

    这种方式与继承Thread类的方法之间的差别如下:

    1、线程只是实现Runnable或实现Callable接口,还可以继承其他类。

    2、这种方式下,多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。

    3.继承Thread类只需要this就能获取当前线程。不需要使用Thread.currentThread()方法

    4、继承Thread类的线程类不能再继承其他父类(Java单继承决定)。

    5、前三种的线程如果创建关闭频繁会消耗系统资源影响性能,而使用线程池可以不用线程的时候放回线程池,用的时候再从线程池取,项目开发中主要使用线程池的方式创建多个线程。

    6.实现接口的创建线程的方式必须实现方法(run() call())。

    展开全文
  • Java线程

    2020-12-21 16:19:13
    目录 理解线程的概念 ... 在Java中,每次程序运行至少启动2个线程:一个是main线程,一个是垃圾收gc集线程。每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM实际上就是在操作系统中启
  • 主要介绍了Java创建线程的两种方式,针对Java创建线程的两种方式进行比较,感兴趣的小伙伴们可以参考一下
  • Java创建线程的三种方法

    千次阅读 2021-02-08 13:51:51
    Java创建线程的三种方法 继承Thread类 实现Runnable接口 实现Callable接口 方法一:继承Thread类 自定义线程类继承Thread类 重写run()方法,编写线程执行体 创建线程对象,调用start()方法开启线程 // 自定义...

    Java创建线程的三种方法

    1. 继承Thread类
    2. 实现Runnable接口
    3. 实现Callable接口

    方法一:继承Thread类

    • 自定义线程类继承Thread类
    • 重写run()方法,编写线程执行体
    • 创建线程对象,调用start()方法开启线程
    // 自定义线程类继承Thread类
    public class TestThread1 extends Thread {
        private String threadName;
    
        public TestThread1(String threadName) {
            this.threadName = threadName;
        }
    	// 重写run()方法,编写线程执行体
        public void run() {
            //线程体
            for (int i = 0; i < 20; i++) {
                System.out.println(threadName + i);
            }
        }
    
        public static void main(String[] args) {
    	//创建线程对象,调用start()方法开启线程
            //创建线程对象一
            TestThread1 testThread11 = new TestThread1("我是线程一");
            //调用Start方法开启线程
            testThread11.start();
            //创建线程对象二
            TestThread1 testThread12 = new TestThread1("我是线程二");
            //调用Start方法开启线程
            testThread12.start();
    
        }
    }
    

    方法二:实现Runnable接口

    • 定义MyRunnable类实现Runnable接口
    • 实现Run()方法,编写线程执行体
    • 创建线程对象,调用start()方法开启线程
    public class TestThread2 implements Runnable {
        private String threadName;
        public TestThread2(String threadName){
            this.threadName=threadName;
        }
        public void run(){
            //线程体
            for (int i = 0; i < 20; i++) {
                System.out.println(threadName+i);
            }
        }
    
        public static void main(String[] args) {
            //创建Runnable接口的实现类对象
            TestThread2 testThread21=new TestThread3("我是线程一");
            TestThread2 testThread22=new TestThread3("我是线程二");
            //通过线程对象来开启线程
            new Thread(testThread21).start();
            new Thread(testThread22).start();
        }
    }
    
    

    方法三:实现Callable接口

    • 实现Callable接口,需要返回值类型
    • 重写call方法,需要抛出异常
    • 创建目标对象
    • 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
    • 提交执行:Future< Boolean> result1 = ser.submit(t1);
    • 获取结果:boolean r1=result1.get()
    • 关闭服务:ser.shutdownNow();
    import java.util.concurrent.*;
    
    public class TestThread4 implements Callable<Boolean> {
        private String threadName;
    
        public TestThread4(String threadName) {
            this.threadName = threadName;
        }
    
        public Boolean call() {
            //线程体
            for (int i = 0; i < 30; i++) {
                System.out.println(threadName + i);
            }
            return true;
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            TestThread4 t1 = new TestThread4("线程一");
            TestThread4 t2 = new TestThread4("线程二");
            //创建执行服务
            ExecutorService ser = Executors.newFixedThreadPool(2);
            //提交执行
            Future<Boolean> r1 = ser.submit(t1);
            Future<Boolean> r2 = ser.submit(t2);
            //获取结果
            boolean rs1 = r1.get();
            boolean rs2 = r2.get();
            //关闭服务
            ser.shutdownNow();
    
        }
    }
    
    
    展开全文
  • Java创建线程的四种方式

    千次阅读 2021-07-07 17:10:26
    而在JDK5之后,又新增了两种,实现Callable接口和使用线程池创建线程。 方式一:继承Thread类 使用步骤: 定义子类继承Thread类。 子类重写Thread类的run()方法。 创建Thread子类对象,即创建了线程对象。 调用...
  • Java创建线程

    千次阅读 2022-04-05 22:49:44
    既然说到线程,在这里就给大家普及一下线程线程(Thread): 是操作系统能够进行运算调度的...进程:简简单单,我们日常使用的QQ就是一个进程,进程可以理解为就是一个软件,线程则就是这个软件的一些功
  • 但在多线程的异步开发模式下,数据的传递和返回和同步开发模式有很大的区别。由于线程的运行和结束是不可预料的,因此,在传递和返回数据时就无法象函数一样通过函数参数和return语句来返回数据
  • java创建线程的四种方式

    千次阅读 2022-03-14 11:52:41
    4.使用线程池创建线程 1.直接初始化Thead类,实现Runnable接口 查看Thread类源码可以发现,有下面这么一个构造参数,target是线程启动的时候要调用的方法(Runnable接口有个run方法),如果为空,那这个类的运行...
  • 主要介绍了Java编程中线程创建与守护线程,是Java线程并发编程的基础,需要的朋友可以参考下
  • 详细的介绍了java中创建两种线程的方法和区别
  • 如何在java中创建一个线程

    千次阅读 2021-03-04 09:01:44
    java中创建一个线程有两种方法:第一种:将类声明为Thread的子类。并子类应重写Thread类的run方法并创建start方法启动线程。第二种:实现Runnable接口,并覆盖接口的run方法,将线程的任务代码封装到run方法;...
  • Java中创建线程的4种方式以及区别

    千次阅读 2018-08-01 17:36:58
    Java可以用三种方式来创建线程,如下所示: 1)继承Thread类创建线程 2)实现Runnable接口创建线程 3)使用Callable和Future创建线程 4)匿名类创建线程(new) 下面让我们分别来看看这三种创建...
  • 主要介绍了java 创建线程的方法总结的相关资料,需要的朋友可以参考下
  • 主要介绍了Java使用Callable和Future创建线程操作,结合实例形式分析了java使用Callable接口和Future类创建线程的相关操作技巧与注意事项,需要的朋友可以参考下
  • 主要介绍了Java使用Thread创建线程并启动操作,结合实例形式分析了Java基于Thread类的多线程定义与启动简单操作技巧,需要的朋友可以参考下
  • java线程实验报告

    2020-11-07 10:06:39
    应用图形用户接口和多线程的知识,编写一个应用程序实现下述功能:当单击“开始”按钮时随机产生一个两位整数不断在文本框上显示(每隔300毫秒显示一次),当单击“停止”按钮时,停止显示并将当前产生的数显示在一...
  • 实现Runnable接口的类必须使用Thread类的实例才能创建线程,通过Runnable接口创建线程分为以下两步
  • 主要介绍了Java线程中线程的两种创建方式及比较代码示例,简单介绍了线程的概念,并行与并发等,然后通过实例代码向大家展示了线程的创建,具有一定参考价值,需要的朋友可以了解下。
  • Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。
  •  为什么Java要提供两种方法来创建线程呢?它们都有哪些区别?相比而言,哪一种方法更好呢?  在Java中,类仅支持单继承,也是说,当定义一个新的类的时候,它只能扩展一个外部类.这样,如果创建自定义线程
  • Java中线程Thread总结

    2020-12-22 18:42:43
     在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。  要注意的是Thread类也实现了Runnable接口,因此,从Thread类继承的类的实例也可以作为target传入这个构造方法。可通过这种方法实现多个线程的...
  • Java之多线程创建

    千次阅读 2019-03-20 19:10:31
    Java线程归纳前言传统的线程创建继承Thread类实现Runnable接口两者的共同点两者差别JDK 1.5开始出现的线程创建 前言 进程是资源分配的最小单位,而线程是执行任务的最小的单位。进程里的线程可以共享该进程拥有的...
  • java常见创建线程的三种方式

    千次阅读 2021-06-11 15:38:06
    创建线程的方法主要有如下三种: 方式1]继承Thread类创建线程 //使用方法1:继承Thread,重写其run()方法 new MyThread().start(); //使用方法2:创建匿名内部类Thread,重写其run()方法 new Thread() { @...
  • java创建线程(Thread)的5种方式

    千次阅读 2021-01-16 17:07:50
    java创建线程(Thread)的4种方式方式一:继承于Thread类方式二:实现Runnable接口方式三:实现Callable接口方式四:使用线程池 方式一:继承于Thread类 步骤: 1.创建一个继承于Thread类的子类 2.重写Thread类的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,013,929
精华内容 405,571
关键字:

java中新建线程

java 订阅
友情链接: html_completewords.rar