精华内容
下载资源
问答
  • Java创建线程的三种方式
    千次阅读
    2022-03-11 15:51:32

    需要自己导入commons io jar包,直接从官网下载即可。
    1.通过继承Thread类创建线程,需要重写run()方法,通过start()开启线程

    package com.MyThread;
    import org.apache.commons.io.FileUtils;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    
    /**
     * @Author: Mengqingnan
     * @Descriiption:
     * @Date:Created in 14:03 2022/3/11
     * @Modified By:
     */
    //多线程同步下载图片
    public class DownPng extends Thread{
        private String url;
        private String filename;
    
        public DownPng(String url, String filename) {
            this.url = url;
            this.filename = filename;
        }
    
        @Override
        public void run() {
            WebDownloader down = new WebDownloader();
            down.downloader(url,filename);
            System.out.println(filename + "下载成功!");
        }
    
        public static void main(String[] args) {
            DownPng downPng1 = new DownPng("https://www.kuangstudy.com/assert/images/index_topleft_logo.png","1.png");
            DownPng downPng2 = new DownPng("https://www.kuangstudy.com/assert/images/index_topleft_logo.png","2.png");
            DownPng downPng3 = new DownPng("https://www.kuangstudy.com/assert/images/index_topleft_logo.png","3.png");
            downPng1.start();
            downPng2.start();
            downPng3.start();
        }
    }
    class WebDownloader{
        //下载方法
        public void downloader(String url,String filename){
            try {
                FileUtils.copyURLToFile(new URL(url),new File(filename));
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("IO异常,downloader方法出现问题。");
            }
        }
    }
    

    2.通过实现Runnable接口创建线程,需要重写run()方法,并且需要通过Thread实例化对象来调用start()方法

    package com.MyThread;
    import org.apache.commons.io.FileUtils;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    
    /**
     * @Author: Mengqingnan
     * @Descriiption:
     * @Date:Created in 14:03 2022/3/11
     * @Modified By:
     */
    //多线程同步下载图片
    public class DownPngbyRunnable implements Runnable{
        private String url;
        private String filename;
    
        public DownPngbyRunnable(String url, String filename) {
            this.url = url;
            this.filename = filename;
        }
        @Override
        public void run() {
            WebDownloader down = new WebDownloader();
            down.downloader(url,filename);
            System.out.println(filename + "通过Runnable实现类创建的线程下载成功!");
        }
    
        public static void main(String[] args) {
            DownPngbyRunnable downPng1 = new DownPngbyRunnable("https://www.kuangstudy.com/assert/images/index_topleft_logo.png","1.png");
            DownPngbyRunnable downPng2 = new DownPngbyRunnable("https://www.kuangstudy.com/assert/images/index_topleft_logo.png","2.png");
            DownPngbyRunnable downPng3 = new DownPngbyRunnable("https://www.kuangstudy.com/assert/images/index_topleft_logo.png","3.png");
            new Thread(downPng1).start();
            new Thread(downPng2).start();
            new Thread(downPng3).start();
        }
    }
    

    3.通过实现Callable接口创建线程,需要重写call()方法

    package com.MyThread;
    
    import javax.xml.transform.Result;
    import java.util.concurrent.*;
    
    /**
     * @Author: Mengqingnan
     * @Descriiption:
     * @Date:Created in 15:35 2022/3/11
     * @Modified By:
     */
    //3.通过Callable实现类创建线程
    public class TestCallable implements Callable<Boolean> {
        private String url;
        private String name;
    
        public TestCallable(String url, String name) {
            this.url = url;
            this.name = name;
        }
    
        @Override
        public Boolean call() throws Exception {
            WebDownloader down = new WebDownloader();
            down.downloader(url,name);
            System.out.println("下载了文件名为:"+name);
            return true;
        }
    
        public static void main(String[] args) {
            TestCallable t1 = new TestCallable("https://www.kuangstudy.com/assert/images/indexlogo.png","111.jpg");
            TestCallable t2 = new TestCallable("https://www.kuangstudy.com/assert/images/indexlogo.png","222.jpg");
            TestCallable t3 = new TestCallable("https://www.kuangstudy.com/assert/images/indexlogo.png","333.jpg");
    
            //创建执行服务
            ExecutorService ser = Executors.newFixedThreadPool(3);
    
            //提交执行
            Future<Boolean> submit1 = ser.submit(t1);
            Future<Boolean> submit2 = ser.submit(t2);
            Future<Boolean> submit3 = ser.submit(t3);
    
            //获取结果
            try {
                boolean r1 = submit1.get();
                boolean r2 = submit2.get();
                boolean r3 = submit3.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            //关闭服务
            ser.shutdown();
        }
    }
    
    
    更多相关内容
  • Java创建线程

    千次阅读 2022-04-05 22:49:44
    既然说到线程,在这里就给大家普及一下线程线程(Thread): 是操作系统能够进行运算调度的最小单位。 它被包含在进程之中,是进程中的实际运作单位。 一个线程指的是进程中一个单一顺序的控制流。 ...

    目录

    既然说到线程,在这里就给大家普及一下线程。

    线程(Thread):

    那么,进程是什么呢?

    接下来,就让我们步入主题:

    在 Java 中,是这样说线程的:

    创建一个新的执行线程有两种方法。 

    第一种:创建一个类实现 Thread 类

     创建线程的第二种方式:使用 Thread(Runnable target) 构造方法,创建对象


    既然说到线程,在这里就给大家普及一下线程。

    🎇🎇🎇🎇🎇🎇🎇🎇

    线程(Thread):

    • 是操作系统能够进行运算调度的最小单位。
    • 它被包含在进程之中,是进程中的实际运作单位。
    • 一个线程指的是进程中一个单一顺序的控制流。

    🥂🥂🥂

    其实:进程在我们计算机中我们随时都在使用:按住 Ctrl + shift + esc

    watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA546L5L2z5Lyf4pmq,size_16,color_FFFFFF,t_70,g_se,x_16

    这个就是一个进程,在计算机中,线程就是进程中的一个执行单元。

    那么,进程是什么呢?

    进程:简简单单,我们日常中使用的QQ就是一个进程进程可以理解为就是一个软件,线程则就是这个软件中的一些功能,多个线程同时工作,才能使得进程工作。🤔🤔🤔。

    使用官方的话来描述进程:

    是计算机中的程序关于某数据集合上的一次运行活动,是操作系统进行资源分配与调度的基本单位。

    接下来,就让我们步入主题:

    ⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰⏰

    在 Java 中,是这样说线程的:

    Java中,Thread类定义为:继承 了祖先类 Object ,实现了 Runable 接口。

    public class Thread extends Object implements Runnable

    线程是程序(进程)中执行的线程。

    Java虚拟机允许应用程序同时执行多个执行线程。 


    每个线程都有优先权。 具有较高优先级的线程优先于优先级较低的线程执行。 每个线程可能也可能不会被标记为守护程序。 当在某个线程中运行的代码创建一个新的Thread对象时,新线程的优先级最初设置为等于创建线程的优先级,并且当且仅当创建线程是守护进程时才是守护线程。 

    当Java虚拟机启动时,通常有一个非守护进程线程(通常调用某些指定类的名为main的方法)。 Java虚拟机将继续执行线程,直到发生以下任一情况: 

    已经调用了Runtime类的exit方法,并且安全管理器已经允许进行退出操作。 
    所有不是守护进程线程的线程都已经死亡,无论是从调用返回到run方法还是抛出超出run方法的run 。 


    创建一个新的执行线程有两种方法。 

    第一种:创建一个类实现 Thread 类

    package stu.my.cdn.creadthread.p1;
    
    /**
     * 创建线程的第一种方式:创建类,实现 Thread 方法
     */
    public class MyThread extends Thread {
    
        /**
         * run () 方法就是子线程要执行的代码
         */
        @Override
        public void run() {
            System.out.println("这是子线程打印的东西");
        }
    
        /**
         * 主线程 main
         */
        public static void main(String [] args) {
            System.out.println("JVM 启动 main线程,main线程执行了main方法");
            // 创建子线程对象
            MyThread thread = new MyThread();
            // 启动线程----启动线程后,会自动执行自定义类中的 run 方法
            thread.start();
            System.out.println("mian 主线程执行结束");
        }
    }
    

     以下是程序的输出结果:

    watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA546L5L2z5Lyf4pmq,size_20,color_FFFFFF,t_70,g_se,x_16

    这种程序执行分为三种方式:

    串行:特殊的并行,程序排队执行,比较耗时,但安全。 

    并发:一个程序执行,在等待阶段,下一个开始。

    并行:简单粗暴,程序一起开始执行,一般效率高。

    从硬件角度来说:如果是单核 CPU ,一个处理器一次只能执行一个线程的情况下,处理器可以使用时间片轮转技术,可以让 CPU 快速的在各个线程之间进行切换,对用户来说,感觉是三个线程在同时执行,如果是多核 CPU ,可以为不同的线程分配不同的 CPU 内核。

    package stu.my.cdn.creadthread.p2;
    
    public class MyThread2 extends Thread{
    
        @Override
        public void run() {
            // 处理异常快捷键 ,选中代码: Ctrl + Alt + T
            try {
                for(int i = 1; i <= 5; i++){
                    System.out.println("子线程==>" + i);
                    int time = (int) (Math.random() * 1000);
                    Thread.sleep(time);     // 线程睡觉,单位是 毫秒, 1s = 1000ms
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            MyThread2 myThread2 = new MyThread2();
            myThread2.start();      // 开启子线程
    
            try {
                for(int i = 1; i <= 5; i++){
                    System.out.println("主线程main==>" + i);
                    int time = (int) (Math.random() * 1000);
                    Thread.sleep(time);     // 线程睡觉,单位是 毫秒, 1s = 1000ms
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

     第一次执行顺序:

     watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA546L5L2z5Lyf4pmq,size_20,color_FFFFFF,t_70,g_se,x_16

    第二次执行顺序 :

     watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA546L5L2z5Lyf4pmq,size_20,color_FFFFFF,t_70,g_se,x_16

    fb528211efe249a6887c1003042963df.gif

     创建线程的第二种方式:使用 Thread(Runnable target) 构造方法,创建对象

    如果已经类已经有了继承的父类,则第一种方式便不再使用这种情况,(因为在JAVA中一个类只能有一个父类):🤔🤔🤔🤔

     那我们便可以使用这种方式:实现接口,使用构造方法,创建线程:

     watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA546L5L2z5Lyf4pmq,size_17,color_FFFFFF,t_70,g_se,x_16

    package stu.my.cdn.creadthread.p3;
    
    /**
     * 当线程已经有父类了,就不能继承 Thread 类的形式创建线程了,可以使用 Runnable 接口的形式
     */
    public class MyRunnable implements  Runnable{
        /**
        * 这里的 run 方法 就相当于我们日常中使用的 main 方法
        * 一旦 线程 start() 就会执行这个方法 
        */
        @Override
        public void run() {
            for(int i = 0; i <= 5; i++){
                System.out.println("MyRunnable implements Runnable 's run method:" + i);
            }
        }
    
        public static void main(String[] args) {
            // 创建 Runnable 接口的实现类
            MyRunnable myRunnable = new MyRunnable();
            // 使用 Runnable 的 Thread(Runnable target) 方法,创建线程对象
            Thread thread = new Thread(myRunnable);
            // 开启线程
            thread.start();
    
            // main 线程
            for (int i = 1; i <= 5; i++){
                System.out.println("Runnable is main:" +i);;
            }
    
            // 使用匿名内部内实现
            Thread thread1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    for(int i = 0; i < 5; i++){
                        System.out.println("use anonymous interior class finished thread create :" + i);
                    }
                }
            });
            // 开启 thread1
            thread1.start();
        }
    }
    

     一样,线程每次并行执行,根据 CPU 核数的不同和允许执行线程的数量,利用对应的技术,在各个线程之间切换,提高执行的效率。

     watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA546L5L2z5Lyf4pmq,size_20,color_FFFFFF,t_70,g_se,x_16

     本期就到这里~~~

    感谢大家阅读~~~68739b582cce4a7289d1d9dede0f0f48.gif

    展开全文
  • java创建线程的四种方式

    千次阅读 2022-03-14 11:52:41
    4.使用线程池创建线程 1.直接初始化Thead类,实现Runnable接口 查看Thread类源码可以发现,有下面这么一个构造参数,target是线程启动的时候要调用的方法(Runnable接口中有个run方法),如果为空,那这个类的运行...

    目录

    1.直接初始化Thead类,实现Runnable接口

    2.继承Thread类

    3.实现callable接口

    4.使用线程池创建线程


    1.直接初始化Thead类,实现Runnable接口

    查看Thread类源码可以发现,有下面这么一个构造参数,target是线程启动的时候要调用的方法(Runnable接口中有个run方法),如果为空,那这个类的运行方法什么都不做

    那我们是否可以直接初始化线程,然后调用start方法启动呢

    答案是可以的

        public Thread(Runnable target) {
            init(null, target, "Thread-" + nextThreadNum(), 0);
        }

    测试代码如下

        public static void main(String args[]){
            new Thread(new Runnable(){
    
                @Override
                public void run() {
                    System.out.println("test create thread by Runable");
                }
            }).start();
        }
        
    Connected to the target VM, address: '127.0.0.1:57009', transport: 'socket'
    test create thread by Runable
    Disconnected from the target VM, address: '127.0.0.1:57009', transport: 'socket'

    当然我们也可以写一个类去实现Runnable接口

    测试代码如下

    class Demo implements Runnable{
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
    
    public static void main(String args[]) {
        Demo d = new Demo();
        Thread thread1 = new Thread(d,"first thread");
        Thread thread2 = new Thread(d,"second thread");
        thread1.start();
        thread2.start();
    }
        
    Connected to the target VM, address: '127.0.0.1:65445', transport: 'socket'
    second thread
    first thread
    Disconnected from the target VM, address: '127.0.0.1:65445', transport: 'socket'

    上面这种方式只new了一个Demo,所以thread1和thread2会共享类中的局部变量

    我们测试下这种方式共享局部变量的效果,可以仔细看看count这个变量的变化,每个线程不是10->1这么变化的,说明count这个变量被2个线程共享了

    class Demo implements Runnable{
    
        private int count =10;
        @Override
        public void run() {
            for(int i=0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+count--);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
        }
    }
    
    public static void main(String args[]) {
        Demo d = new Demo();
        Thread thread1 = new Thread(d,"first thread");
        Thread thread2 = new Thread(d,"second thread");
        thread1.start();
        thread2.start();
    }
    
    Connected to the target VM, address: '127.0.0.1:51427', transport: 'socket'
    first thread10
    second thread9
    first thread8
    second thread7
    second thread6
    first thread5
    second thread4
    first thread3
    first thread2
    second thread2
    first thread1
    second thread1
    second thread0
    first thread-1
    second thread-2
    first thread-3
    second thread-4
    first thread-5
    second thread-6
    first thread-7
    Disconnected from the target VM, address: '127.0.0.1:51427', transport: 'socket'
    
    Process finished with exit code 0
    

    如果我们不想共享类中的变量,那只能初始化2个Demo类,代码如下

    public static void main(String args[]) {
        Demo d1 = new Demo();
        Demo d2 = new Demo();
        Thread thread1 = new Thread(d1,"first thread");
        Thread thread2 = new Thread(d2,"second thread");
        thread1.start();
        thread2.start();
    }
    
    Connected to the target VM, address: '127.0.0.1:65346', transport: 'socket'
    first thread10
    second thread10
    first thread9
    second thread9
    second thread8
    first thread8
    first thread7
    second thread7
    first thread6
    second thread6
    first thread5
    second thread5
    first thread4
    second thread4
    first thread3
    second thread3
    first thread2
    second thread2
    first thread1
    second thread1
    Disconnected from the target VM, address: '127.0.0.1:65346', transport: 'socket'

    2.继承Thread类

    前面我们通过初始化Thread类的方式创建线程,那我们是否可以新建一个类继承Thread类,然后创建线程呢,那肯定是可以的

    测试代码如下

    class Demo extends Thread{
    
        public void run() {
            System.out.println(Thread.currentThread().getName());
    
        }
    }
    
    public static void main(String args[]) {
        Demo d = new Demo();
        Thread thread1 = new Thread(d,"create thread by extends Thread");
        thread1.start();
    }
    
    Connected to the target VM, address: '127.0.0.1:64623', transport: 'socket'
    create thread by extends Thread
    Disconnected from the target VM, address: '127.0.0.1:64623', transport: 'socket'

    3.实现callable接口

    A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call. The Callable interface is similar to Runnable, in that both are designed for classes whose instances are potentially executed by another thread. A Runnable, however, does not return a result and cannot throw a checked exception.(返回结果并可能抛出异常的任务。实现者定义了一个不带参数的方法,称为call。 Callable接口与Runnable接口类似,两者都是为其实例可能由另一个线程执行的类设计的。然而,Runnable不返回结果,也不能抛出检查异常。)

    我们查看jdk中callable类的注释,可以知道几个关键的信息

    1.Callable接口和Runnable接口类似,都是为其他线程执行实例而设计的

    2.Callable可以接受结果

    3.Callable可以检查异常

    通过jdk的FutureTask类,我们可以看到其实现了RunableFuture接口,然后这个接口是继承的Runable

    我们来看一下他的源码

    我们可以通过这个方法来实例化FutureTask

    Creates a FutureTask that will, upon running, execute the given Callable. Params: callable – the callable task Throws: NullPointerException – if the callable is null

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

    然后通过get方法获取返回结果

    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

    Returns result or throws exception for completed task. Params: s – completed state value

    private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

    测试代码如下

    class Demo implements Callable{
    
        @Override
        public Object call() throws Exception {
            int sum=0;
            for(int i=0;i<10;i++){
                sum=sum+i;
                Thread.sleep(300);
            }
            System.out.println("sum:"+sum);
            return sum;
        }
    }
    
    
    public static void main(String args[]) throws Exception{
    
        System.out.println("time1:"+new Date());
        Demo d = new Demo();
        FutureTask futureTask = new FutureTask(d);
        Thread thread = new Thread(futureTask);
        thread.start();
        System.out.println("time2:"+new Date());
        Object sum = futureTask.get(5,TimeUnit.SECONDS);
        System.out.println("time3:"+new Date());
        System.out.println(sum);
    
    }
    
    Connected to the target VM, address: '127.0.0.1:60755', transport: 'socket'
    time1:Fri Mar 11 17:54:19 CST 2022
    time2:Fri Mar 11 17:54:19 CST 2022
    sum:45
    time3:Fri Mar 11 17:54:22 CST 2022
    45
    Disconnected from the target VM, address: '127.0.0.1:60755', transport: 'socket'

    我们可以发现time2和time3之间间隔了3s,然后获得了结果

    4.使用线程池创建线程

    线程池创建线程的优点

    Thread pools address two different problems: they usually provide improved performance when executing large numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and managing the resources, including threads, consumed when executing a collection of tasks. Each ThreadPoolExecutor also maintains some basic statistics, such as the number of completed tasks.(线程池解决两个不同的问题:它们通常在执行大量异步任务时提高性能,因为减少了每个任务的调用开销,并且它们提供了一种方法来限制和管理执行任务集合时消耗的资源(包括线程)。每个ThreadPoolExecutor还维护一些基本的统计信息,比如完成任务的数量。)

    1.使用ThreadPoolExecutor创建线程.这种方式比较灵活

    Params:

    • corePoolSize – the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set
    • maximumPoolSize – the maximum number of threads to allow in the pool
    • keepAliveTime – when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
    • unit – the time unit for the keepAliveTime argument
    • workQueue – the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
    • threadFactory – the factory to use when the executor creates a new thread
    • handler – the handler to use when execution is blocked because the thread bounds and queue capacities are reached
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

    下面我们来测试一下,这里使用callable,当然也可以使用runnable

    class Demo implements Callable{
    
        @Override
        public Object call() throws Exception {
            int sum=0;
            for(int i=0;i<10;i++){
                sum=sum+i;
                Thread.sleep(300);
            }
            System.out.println("sum:"+sum);
            return sum;
        }
    }
    
        public static void main(String args[]) throws Exception{
    
            ThreadPoolExecutor pool = new ThreadPoolExecutor(10,20,60L,TimeUnit.SECONDS,new SynchronousQueue<>(), new ThreadFactoryBuilder().setNameFormat("test thread pool").build(),new ThreadPoolExecutor.AbortPolicy());
            Demo d = new Demo();
            Future f = pool.submit(d);
            System.out.println("当前时间:"+new Date());
            Object result = f.get(5L,TimeUnit.SECONDS);
            System.out.println("当前时间:"+new Date()+"==结果:"+result);
        }
        
    当前时间:Mon Mar 14 11:28:42 CST 2022
    sum:45
    当前时间:Mon Mar 14 11:28:45 CST 2022==结果:45

    2.使用Executors创建线程池

    这种方法比较简单,其实就是对上面的方法进行了一些封装,建议使用上面的方法,因为可以看到具体的参数

    Executorst提供了几个常见构造方法

    • newFixedThreadPool--
    • newSingleThreadExecutor
    • newCachedThreadPool
    • newScheduledThreadPool

    我们来找一个这个类的构造参数看一下

    Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available. If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks. The threads in the pool will exist until it is explicitly shutdown.
    Params:
    nThreads – the number of threads in the pool
    Returns:
    the newly created thread pool
    Throws:
    IllegalArgumentException – if nThreads <= 0

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    测试一下

    class Demo implements Runnable{
    
        @Override
        public void run() {
            int sum=0;
            for(int i=0;i<10;i++){
                sum=sum+i;
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("sum:"+sum);
    
        }
    }
    
        public static void main(String args[]) throws Exception{
            ExecutorService executorService = Executors.newFixedThreadPool(10);
            Demo d = new Demo();
            executorService.submit(d);
        }
        
    Connected to the target VM, address: '127.0.0.1:55962', transport: 'socket'
    sum:45
    Disconnected from the target VM, address: '127.0.0.1:55962', transport: 'socket'

    展开全文
  • java创建线程(Thread)的5种方式

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

    方式一:继承于Thread类

    步骤:
    1.创建一个继承于Thread类的子类
    2.重写Thread类的run() --> 将此线程执行的操作声明在run()中
    3.创建Thread类的子类的对象
    4.通过此对象调用start()执行线程

    示例代码(遍历100以内的所有的偶数):

    package atguigu.java;
    
    //1.创建一个继承于Thread类的子类
    class MyThread extends Thread {
        //2.重写Thread类的run()
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + ":" + i);
                }
            }
        }
    }
    
    
    public class ThreadTest {
        public static void main(String[] args) {
            //3.创建Thread类的子类的对象
            MyThread t1 = new MyThread();
    
            //4.通过此对象调用start():①启动当前线程 ② 调用当前线程的run()
            t1.start();
    
            /*问题一:我们不能通过直接调用run()的方式启动线程,
            这种方式只是简单调用方法,并未新开线程*/
            //t1.run();
    
            /*问题二:再启动一个线程,遍历100以内的偶数。
            不可以还让已经start()的线程去执行。会报IllegalThreadStateException*/
            //t1.start();
    
            //重新创建一个线程的对象
            MyThread t2 = new MyThread();
            t2.start();
    
            //如下操作仍然是在main线程中执行的。
            for (int i = 0; i < 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + ":" + i + "***********main()************");
                }
            }
        }
    }
    
    

    输出结果(部分):
    在这里插入图片描述

    方式二:实现Runnable接口

    步骤:
    1.创建一个实现了Runnable接口的类
    2.实现类去实现Runnable中的抽象方法:run()
    3.创建实现类的对象
    4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
    5.通过Thread类的对象调用start()
    ① 启动线程
    ②调用当前线程的run()–>调用了Runnable类型的target的run()

    示例代码(遍历100以内的所有的偶数):

    package atguigu.java;
    
    //1.创建一个实现了Runnable接口的类
    class MThread implements Runnable {
    
        //2.实现类去实现Runnable中的抽象方法:run()
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + ":" + i);
                }
            }
        }
    }
    
    public class ThreadTest1 {
    
        public static void main(String[] args) {
            //3.创建实现类的对象
            MThread mThread = new MThread();
    
            //4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
            Thread t1 = new Thread(mThread);
            t1.setName("线程1");
    
            //5.通过Thread类的对象调用start():① 启动线程 ②调用当前线程的run()-->调用了Runnable类型的target的run()
            t1.start();
    
            //再启动一个线程,遍历100以内的偶数
            Thread t2 = new Thread(mThread);
            t2.setName("线程2");
            t2.start();
        }
    
    }
    

    输出结果(部分):
    在这里插入图片描述

    方式一和方式二的比较:

    • 开发中优先选择实现Runnable接口的方式
    • 原因:
      (1)实现的方式没有类的单继承性的局限性
      (2)实现的方式更适合来处理多个线程有共享数据的情况
    • 相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中

    方式三:实现Callable接口

    步骤:
    1.创建一个实现Callable的实现类
    2.实现call方法,将此线程需要执行的操作声明在call()中
    3.创建Callable接口实现类的对象
    4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
    5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
    6.获取Callable中call方法的返回值

    实现Callable接口的方式创建线程的强大之处

    • call()可以有返回值的
    • call()可以抛出异常,被外面的操作捕获,获取异常的信息
    • Callable是支持泛型的

    示例代码1:

    package com.atguigu.java2;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    //1.创建一个实现Callable的实现类
    class NumThread implements Callable {
        //2.实现call方法,将此线程需要执行的操作声明在call()中
        @Override
        public Object call() throws Exception {
            int sum = 0;
            //把100以内的偶数相加
            for (int i = 1; i <= 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(i);
                    sum += i;
                }
            }
            return sum;
        }
    }
    
    public class ThreadNew {
        public static void main(String[] args) {    
            //3.创建Callable接口实现类的对象
            NumThread numThread = new NumThread();
    
            //4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
            FutureTask futureTask = new FutureTask(numThread);
    
            //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
            new Thread(futureTask).start();
    
            try {
                //6.获取Callable中call方法的返回值
                //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
                Object sum = futureTask.get();
                System.out.println("总和为:" + sum);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    

    输出结果(尾部):
    在这里插入图片描述
    示例代码2:

    package com.jian8.juc.thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    import java.util.concurrent.TimeUnit;
    
    class MyThread implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("Callable come in");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1024;
        }
    }
    
    public class CallableDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            //使用构造方法:FutureTask(Callable<V> callable)
            FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread());
    
            new Thread(futureTask, "AAA").start();
            //new Thread(futureTask, "BBB").start();//复用,直接取值,不要重启两个线程
            //PS:多个线程来抢一个futureTask,里面的计算方法call()只计算一次,要想多次算,要创建多个FutureTask<V>对象
    
            int a = 100;
            int b = 0;
    
            //b = futureTask.get();//要求获得Callable线程的计算结果,如果没有计算完成就要去强求,会导致堵塞,直到计算完成
            while (!futureTask.isDone()) {//当futureTask完成后取值
                b = futureTask.get();
            }
            System.out.println("Result=" + (a + b));
        }
    }
    

    运行结果:
    在这里插入图片描述

    方式四:使用线程池

    线程池好处:
    1.提高响应速度(减少了创建新线程的时间)
    2.降低资源消耗(重复利用线程池中线程,不需要每次都创建)
    3.便于线程管理

    核心参数:

    • corePoolSize:核心池的大小
    • maximumPoolSize:最大线程数
    • keepAliveTime:线程没有任务时最多保持多长时间后会终止

    步骤:
    1.以方式二或方式三创建好实现了Runnable接口的类或实现Callable的实现类
    2.实现run或call方法
    3.创建线程池
    4.调用线程池的execute方法执行某个线程,参数是之前实现Runnable或Callable接口的对象

    示例代码:

    package com.atguigu.java2;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadPoolExecutor;
    
    class NumberThread implements Runnable {
        @Override
        public void run() {
            //遍历100以内的偶数
            for (int i = 0; i <= 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + ": " + i);
                }
            }
        }
    }
    
    class NumberThread1 implements Runnable {
        @Override
        public void run() {
            //遍历100以内的奇数
            for (int i = 0; i <= 100; i++) {
                if (i % 2 != 0) {
                    System.out.println(Thread.currentThread().getName() + ": " + i);
                }
            }
        }
    }
    
    
    public class ThreadPool {
    
        public static void main(String[] args) {
            //1. 提供指定线程数量的线程池
            ExecutorService service = Executors.newFixedThreadPool(10);
    
            //输出class java.util.concurrent.ThreadPoolExecutor
            System.out.println(service.getClass());
    
            ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
            //自定义线程池的属性
    //        service1.setCorePoolSize(15);
    //        service1.setKeepAliveTime();
    
            //2. 执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象
            service.execute(new NumberThread());//适用于Runnable
            service.execute(new NumberThread1());//适用于Runnable
    //        service.submit(Callable callable);//适合使用于Callable
    
            //3. 关闭连接池
            service.shutdown();
        }
    
    }
    
    

    输出结果(部分):
    在这里插入图片描述

    方式五:使用匿名类

    Thread thread = new Thread(new Runnable() {
    	@Override
    	public void run() {
    		// 线程需要执行的任务代码
    		System.out.println("子线程开始启动....");
    		for (int i = 0; i < 30; i++) {
    			System.out.println("run i:" + i);
    		}
    	}
    });
    thread.start();
    

    或者

    new Thread(() -> {
    	System.out.println(Thread.currentThread().getName() + "\t上完自习,离开教室");
    }, "MyThread").start();
    
    展开全文
  • ======创建线程的方式====== 继承Thead类,重写run()方法 实现Runnable类,重写run()方法 使用lombda 实现Callable类,重写call()方法 使用线程池 ======停止线程的方式====== 使用stop()方法 使用suspend()和resume()...
  • Java 创建线程的三种方式总结

    万次阅读 2020-12-03 11:13:19
    Java 创建线程的三种方式总结 我们在开发中,为了提高程序的运行效率,经常会使用多线程的方式来实现并发操作。 那么创建线程有几种方式呢? 1、继承 Thread 类 直接继承 Thread 即可实现多线程。Thread 本质上也是...
  • 看到这个标题的小伙伴先别着急喷我……在面试的时候,我们经常会被问到这种基础题:Java创建线程的方式有几种? 比较正常的答法当然是三种: 继承Thread 实现Runnable接口 实现callable接口 一般来说这种属于送分...
  • Java创建线程及配合使用Lambda

    万次阅读 2018-08-30 16:32:13
    说明Java创建线程的三种方式,以及在创建线程的时候利用Lambda简化代码的实现
  • Java创建线程的四种方式

    万次阅读 多人点赞 2018-07-28 22:10:16
    1.继承Thread类实现多线程  run()为线程类的核心方法,相当于主线程的main方法,是每个线程的入口  a.一个线程调用 两次start()方法将会抛出线程状态异常,也就是的start()只可以被调用一次   b.native生明的...
  • java创建线程的两种方式及区别

    千次阅读 2018-07-24 18:35:47
    本文将介绍创建线程的两种方式,示例代码在下面,复制粘贴即可 继承Thread类方式和实现Runnable接口方式 区别:由于在开发的过程中,很多的类都会用到继承的方式,如果采用继承的方式会让各个类之间的关系变得错综...
  • Java创建线程四种方式: 1. 继承Thread类; 2. 实现Runnable接口; 3. 实现Callable接口,实例化FutureTask类; 4. 创建线程池(以下用Executor框架实现) 说明:这四种方式都潜移默化都用到了Thread类(表示线程),...
  • java创建线程安全的Set集合

    千次阅读 2021-12-27 14:48:32
    java创建线程安全的Set集合的几种方法的对比:CopyOnWriteArraySet、Collections.synchronizedSet()、Collections.newSetFromMap(new ConcurrentHashMap())、ConcurrentHashMap.newKeySet()
  • java创建线程的3种方式

    千次阅读 2018-07-12 17:33:01
    Java 提供了三种创建线程的方法:通过实现 Runnable 接口;通过继承 Thread 类本身;通过 Callable 和 Future 创建线程通过实现 Runnable 接口package com.demo.thread.Runnable; public class RunnableDemo ...
  • 3,使用Executor框架创建线程池。Executor框架是juc里提供的线程池的实现。 调用线程的start():启动此线程;调用相应的run()方法 继承于Thread类的线程类,可以直接调用start方法启动线程(使用sta...
  • 详解 Java 创建线程的三种方式

    千次阅读 2021-01-18 16:02:50
    java创建线程的方式主要有三种: 继承Thread类创建线程 实现Runnable接口创建线程 使用Callable和Future创建线程 1. 通过继承Thread类创建线程 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就...
  • java 创建线程的三种方式、创建线程池的四种方式

    万次阅读 多人点赞 2019-02-23 21:01:44
    java创建线程的三种方式: 继承Thread类创建线程类 实现Runnable接口 通过Callable和Future创建线程 java创建线程池的四种方式: newCachedThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理...
  • Java创建线程的五种方法

    千次阅读 2021-12-31 15:01:09
    Java创建线程的五种方法总结
  • java创建线程的三种方式及其对比

    万次阅读 多人点赞 2014-11-14 22:14:15
    Java创建线程主要有三种方式: 一、继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。 (2)创建Thread子类的实例...
  • java常见创建线程的三种方式

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

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

    千次阅读 2017-10-19 20:14:30
    Java线程中,有以下三种方式可以实现线程创建。 通过继承Thread类,调用Thread的start方法实现线程创建 实现Runnable接口 实现Callable接口 继承Thread可以实现线程创建,但当我们需要继承其他父类的时候...
  • Java创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。
  • Java创建线程的8种方式

    万次阅读 多人点赞 2018-07-21 21:16:51
    Java创建启动线程的多种方式 1、继承Thread类,重写run()方法 2、实现Runnable接口,重写run() 3、匿名内部类的方式 4、带返回值的线程(实现implements Callable&lt;返回值类型&gt;)————以上3...
  • 如何在java创建一个线程

    千次阅读 2021-03-04 09:01:44
    java中创建一个线程有两种方法:第一种:将类声明为...最后通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。首先我们创建线程的目的是为了开启一条执行路径,去...
  • Java 线程创建的四种方式

    千次阅读 2022-03-04 15:35:34
    Java 线程创建的四种方式 所有测试用例使用的是 jdk8 ,版本不同可能会有所不同,建议自己亲手试试。 Thread 方式 通过继承Thread类来创建新的线程(不推荐)。示例如下: 创建类 public class ThreadDemo extends ...
  • Java1.5版本开始,就提供了 Callable 和 Future 来创建线程,这种方式也是在Java程序员面试中经常会被问到的问题。 上一小节介绍了Thread和Runnable两种方式创建线程,不过这两种方式创建线程都有一个缺陷:在执行...
  • 众所周知,我们在创建线程时有四种方法可以用,分别是: 1、继承Thread类创建线程 2、实现Runnable接口创建线程 3、使用Callable和Future创建线程 4、使用线程池创建(使用java.util.concurrent.Executor接口) 其中...
  • 昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的问题:你说一说 Java 创建线程都有哪些方式? 这哥们心中窃喜,这个老生常谈的问题早已背的滚瓜烂熟,于是很流利的说了出来。 Java 创建线程有两种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 981,748
精华内容 392,699
关键字:

java创建线程

java 订阅
友情链接: dianziqin2.1.rar