Java——多线程高并发系列之创建多线程的四种方式(Thread、Runnable、Callable、线程池)

简介: Java——多线程高并发系列之创建多线程的四种方式(Thread、Runnable、Callable、线程池)

文章目录:


写在前面

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

Demo2(实现Runnable接口,重写run()方法)

传统写

匿名内部类写法

Demo3(实现Callable接口,重写call()方法)

Demo4(线程池 + Callable接口)

写在前面


历时一个星期,终于整完了Java多线程高并发这个系列的相关内容,这是最后一篇关于多线程的文章了,打算回到最初学习多线程的起点:总结一下创建多线程的四种方式吧。

Demo1(继承Thread,重写run()方法)


package com.szh.begin;
/**
 * 实现多线程的第一种方式:继承Thread类,重写run()方法
 */
public class Test01 {
    static class MyThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " ---> " + i);
            }
        }
    }
    public static void main(String[] args) {
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        t1.setName("t1");
        t2.setName("t2");
        //start方法的作用是:启动一个分支线程,在JVW中开辟一个新的栈空间
        //只要栈空间开辟出来,start方法就结束了,线程就启动成功了,启动成功的线程会自动调用run方法
        //run方法在分支线程的栈底部,main方法在主线程的栈底部,run和main是平级的
        t1.start();
        t2.start();
        //上面的代码也可以写成下面这种形式,只不过需要再来一个有参构造
//        new MyThread("t1").start();
//        new MyThread("t2").start();
    }
}

Demo2(实现Runnable接口,重写run()方法)


传统写法

package com.szh.begin;
/**
 * 实现多线程的第二种方式:实现Runnable接口,重写run()方法
 * 传统写法
 */
public class Test02 {
    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " ---> " + i);
            }
        }
    }
    public static void main(String[] args) {
        new Thread(new MyRunnable(),"t1").start();
        new Thread(new MyRunnable(),"t2").start();
    }
}


匿名内部类写法

package com.szh.begin;
/**
 * 实现多线程的第二种方式:实现Runnable接口,重写run()方法
 * 匿名内部类写法
 */
public class Test03 {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + " ---> " + i);
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + " ---> " + i);
                }
            }
        }).start();
    }
}

Demo3(实现Callable接口,重写call()方法)


package com.szh.begin;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
 * 实现多线程的第三种方式:实现Callable接口,重写call()方法
 * 使用FutureTask接收线程的执行结果
 */
public class Test05 {
    static class MyCallable implements Callable<Object> {
        @Override
        public Object call() throws Exception {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " ---> " + i);
            }
            return "当前执行线程的id为:" + Thread.currentThread().getId();
        }
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //new一个未来任务类对象,参数传入一个Callable接口实现类对象
        FutureTask<Object> task1=new FutureTask<>(new MyCallable());
        FutureTask<Object> task2=new FutureTask<>(new MyCallable());
        //创建两个线程对象,参数传入一个FutureTask对象,之后启动线程
        new Thread(task1).start();
        new Thread(task2).start();
        //获取t1线程的执行结果
        Object obj1=task1.get();
        Object obj2=task2.get();
        System.out.println(obj1);
        System.out.println(obj2);
    }
}


Demo4(线程池 + Callable接口)


package com.szh.begin;
import java.util.concurrent.*;
/**
 * 实现多线程的第三种方式:实现Callable接口,重写call()方法
 * 使用Future接收线程的执行结果
 */
public class Test04 {
    static class MyCallable implements Callable<Object> {
        @Override
        public Object call() throws Exception {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + " ---> " + i);
            }
            return "当前执行线程的id为:" + Thread.currentThread().getId();
        }
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建一个固定大小的线程池
        ExecutorService service= Executors.newFixedThreadPool(2);
        //提交执行
        Future<Object> future1=service.submit(new MyCallable());
        Future<Object> future2=service.submit(new MyCallable());
        //获取call()方法的返回值(即线程执行结果的返回值)
        Object obj1=future1.get();
        Object obj2=future2.get();
        //打印
        System.out.println(obj1);
        System.out.println(obj2);
        //关闭线程池
        service.shutdown();
    }
}

相关文章
|
1月前
|
存储 前端开发 算法
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(一)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
45 0
|
27天前
Exception in thread “main“ java.lang.NoClassDefFoundError: freemarker/template/Configuration
Exception in thread “main“ java.lang.NoClassDefFoundError: freemarker/template/Configuration
21 0
|
1月前
|
存储 并行计算 Java
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(二)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
64 0
|
18天前
|
Java
Java中的多线程实现:使用Thread类与Runnable接口
【4月更文挑战第8天】本文将详细介绍Java中实现多线程的两种方法:使用Thread类和实现Runnable接口。我们将通过实例代码展示如何创建和管理线程,以及如何处理线程同步问题。最后,我们将比较这两种方法的优缺点,以帮助读者在实际开发中选择合适的多线程实现方式。
23 4
|
1月前
Exception in thread “main“ java.lang.UnsupportedOperationException
Exception in thread “main“ java.lang.UnsupportedOperationException
17 1
|
1月前
|
Java API C++
【C++ 与Qt 线程】C++ std::thread 与Qt qthread多线程混合编程
【C++ 与Qt 线程】C++ std::thread 与Qt qthread多线程混合编程
45 1
|
1月前
|
安全 Java Unix
【C++ 包裹类 std::thread】探索C++11 std::thread:如何使用它来创建、销毁和管理线程
【C++ 包裹类 std::thread】探索C++11 std::thread:如何使用它来创建、销毁和管理线程
44 0
|
17天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
28天前
|
存储 缓存 NoSQL
Redis单线程已经很快了6.0引入多线程
Redis单线程已经很快了6.0引入多线程
31 3
|
30天前
|
消息中间件 安全 Linux
线程同步与IPC:单进程多线程环境下的选择与权衡
线程同步与IPC:单进程多线程环境下的选择与权衡
58 0