前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >多线程基础

多线程基础

作者头像
冬天vs不冷
发布2025-01-20 21:09:11
发布2025-01-20 21:09:11
8200
代码可运行
举报
文章被收录于专栏:springbootspringboot
运行总次数:0
代码可运行

一、基础概念:程序、进程、线程

  • 程序:某种语言编写的指令集合。即静态代码,静态对象。
  • 进程:程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程:有产生、存在和消亡的过程。
  • 线程:进程可进一步细化为线程,是一个程序内部的一条执行路径。 ①若一个进程同一时间并行执行多个线程,就是支持多线程。 ②每个线程拥有独立的栈和程序计数器 ③一个进程的多个线程共享相同堆里的对象,方法区常量
  • 单核和多核CPU的理解 ①单核多线程,一个cup交替执行多个线程。 ②多核则是每个cup执行一个线程。 ③一个Java应用程序java.exe,至少三个线程:main(),gc(),异常处理线程
  • 并行和并发 ①并行:多个CUP同时执行多个任务。 ②并发:一个CUP同时执行多个任务。

例子:单核CUP执行两件事,串行执行时间快,还是多线程执行快? 答:串行执行快。因为单核,执行的总时间一样,而多线程增加了线程切换的时间。

二、继承Thread:多线程的创建和使用

MyThread 继承Thread类,重写run方法,Thread.start()开启新线程,调用Thread.run方法,此时已重写,调用MyThread的run()方法。

代码语言:javascript
代码运行次数:0
运行
复制
//1.创建一个继承于Thread的子类
class MyThread extends Thread{
    //2.重写Thread类的run方法
    @Override
    public void run() {
        //打印10内偶数的操作
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0){
                System.out.println("线程:"+Thread.currentThread().getName()+"的偶数:"+i);
            }
        }
    }
}
public class ThreadCreateTest {
    public static void main(String[] args) {
        //3.创建Thread类的子类的对象
        MyThread t1 = new MyThread();
        //4.通过此对象调用start对象
        t1.start();
        //打印10内奇数的操作
        for (int i = 0; i < 10; i++) {
            if (i % 2 != 0){
                System.out.println("线程:"+Thread.currentThread().getName()+"的奇数:"+i);
            }
        }
    }
}
结果:
线程:Thread-0的偶数:0
线程:main的奇数:1
线程:Thread-0的偶数:2
线程:main的奇数:3
线程:Thread-0的偶数:4
线程:main的奇数:5
线程:main的奇数:7
线程:main的奇数:9
线程:Thread-0的偶数:6
线程:Thread-0的偶数:8
  • 如上图中有两个线程:main线程(主线程)、Thread-0线程(分线程)。
  • main方法中直到t1.start()(启动分线程,并调用分线程run方法);之前只有主线程,之后是主线程和分线程交替执行。
  • 如果t1.run,则不会启动新线程
  • 创建一个Threadl类的子类的对象只能启动一次,启动多次报错。
快捷方式创建:
代码语言:javascript
代码运行次数:0
运行
复制
public class ThreadCreateTest {
    public static void main(String[] args) {
        //匿名内部类方式创建
        new Thread(){
            @Override
            public void run() {
                System.out.println("方式一");
            }
        }.start();
        //Lambda表达式方式
        new Thread(() -> {
            System.out.println("方式二");
        }).start();
    }
}

Thread类实现了Runable函数式接口如下,故创建Thread类也就是实现Runnable的run方法。

代码语言:javascript
代码运行次数:0
运行
复制
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

三、Thread的常用方法

  1. start():启动当前线程;调用当前线程的run()方法。
  2. run():通常需要重写Thread类的此方法,将创建线程要执行的操作声明在此方法中
  3. currentThread():静态方法,返回当前的线程对象。(可以理解为this)
  4. getName():获取当前线程的名字
  5. setName():设置当前线程的名字
代码语言:javascript
代码运行次数:0
运行
复制
class MyThread2 extends Thread{
    @Override
    public void run() {
        Thread.currentThread().setName("分线程");
        String name = Thread.currentThread().getName();
        String name1 = this.getName();
        System.out.println(name);//结果:“分线程”  线程名字已修改
        System.out.println(name == name1);//结果:true  Thread.currentThread() 就是 this
    }
}

public class ThreadCreateTest2 {
    public static void main(String[] args) {
        MyThread2 t2 = new MyThread2();
        t2.start();
    }
}
  1. yield():本地静态方法。释放当前cpu的执行权 当分线程i=4时,释放cup执行权。cup重新选择执行主线程还是分线程
代码语言:javascript
代码运行次数:0
运行
复制
class MyThread3 extends Thread{
    @Override
    public void run() {
        //打印100内偶数的操作
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0){
                System.out.println("线程:"+Thread.currentThread().getName()+"的偶数:"+i);
            }
            if(i == 4){
                System.out.println("释放当前cup执行权");
                Thread.yield();
            }
        }
    }
}
public class ThreadCreateTest3 {
    public static void main(String[] args) {
        MyThread3 t3 = new MyThread3();
        t3.start();
        for (int i = 0; i < 10; i++) {
            if (i % 2 != 0){
                System.out.println("线程:"+Thread.currentThread().getName()+"的奇数:"+i);
            }
        }
    }
}
结果:
线程:Thread-0的偶数:0
线程:main的奇数:1
线程:Thread-0的偶数:2
线程:main的奇数:3
线程:Thread-0的偶数:4
释放当前cup执行权
线程:main的奇数:5
线程:main的奇数:7
线程:Thread-0的偶数:6
线程:main的奇数:9
线程:Thread-0的偶数:8
  1. join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完成以后,线程a才结束阻塞状态
代码语言:javascript
代码运行次数:0
运行
复制
class MyThread4 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0){
                System.out.println("线程:"+Thread.currentThread().getName()+"的偶数:"+i);
            }
        }
    }
}
public class ThreadCreateTest4 {
    public static void main(String[] args) throws InterruptedException {
        MyThread4 t4 = new MyThread4();
        t4.start();
        for (int i = 0; i < 10; i++) {
            if (i % 2 != 0){
                System.out.println("线程:"+Thread.currentThread().getName()+"的奇数:"+i);
            }
            if(i == 3){
                t4.join();
            }
        }
    }
}
结果:
线程:main的奇数:1
线程:Thread-0的偶数:0
线程:main的奇数:3
线程:Thread-0的偶数:2
线程:Thread-0的偶数:4
线程:Thread-0的偶数:6
线程:Thread-0的偶数:8
线程:main的奇数:5
线程:main的奇数:7
线程:main的奇数:9
  1. stop():已过时。当执行此方法时,强制结束当前线程。
  2. sleep(long millitime):静态本地方法。让当前线程睡眠指定毫秒,当前线程处于阻塞状态。 不会让出锁,但是会让出CPU执行权 注:sleep抛异常只能try,不能抛,因为重写的父类方法run没有抛异常,故子类也不能抛。
代码语言:javascript
代码运行次数:0
运行
复制
class MyThread4 extends Thread{
    @Override
    public void run() {
        try {
            sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  1. isAlive:判断当前线程是否存活。

四、线程的调度

  • 调度策略 ①时间片:均匀分配 ②抢占式:高优先级的线程抢占CPU
  • 线程的优先级 ①MAX_PRIORITY:10(最高优先级) ②MIN_PRIORITY:1(最低优先级) ③NORM_PRIORITY:5(默认优先级)
  • 方法 ①getPriority():返回线程的优先值 ②setPriority(int newPriority):改变线程的优先级
  • 说明 ①线程创建时继承父线程的优先级 ②低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用
代码语言:javascript
代码运行次数:0
运行
复制
class MyThread5 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0){
                System.out.println("线程:"+Thread.currentThread().getName()+"的偶数:"+i);
            }
        }
    }
}
public class ThreadCreateTest5 {
    public static void main(String[] args) throws InterruptedException {
        MyThread5 t1 = new MyThread5();
        t1.setPriority(10);
        MyThread5 t2 = new MyThread5();
        System.out.println("线程:"+t1.getName()+"优先级等级为:"+t1.getPriority());
        System.out.println("线程:"+t2.getName()+"优先级等级为:"+t2.getPriority());
        t1.start();
        t2.start();
    }
}
结果:
线程:Thread-0优先级等级为:10
线程:Thread-1优先级等级为:5
线程:Thread-0的偶数:0
线程:Thread-0的偶数:2
线程:Thread-1的偶数:0
线程:Thread-0的偶数:4
线程:Thread-1的偶数:2
线程:Thread-0的偶数:6
线程:Thread-1的偶数:4
线程:Thread-0的偶数:8
线程:Thread-1的偶数:6
线程:Thread-1的偶数:8

五、实现Runnable:多线程的创建和使用

代码语言:javascript
代码运行次数:0
运行
复制
//1、创建实现Runnable接口的类
class MyRunnable implements Runnable{
    //2.实现类去实现Runnable接口的抽象方法run
    @Override
    public void run() {
        //打印100内偶数的操作
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0){
                System.out.println("线程:"+Thread.currentThread().getName()+"的偶数:"+i);
            }
        }
    }
}
public class RunnableCreateTest {
    public static void main(String[] args) {
        //3.创建实现类的对象
        MyRunnable myRunnable = new MyRunnable();
        //4.将对象传入Thread类构造方法
        Thread t1 = new Thread(myRunnable);
        t1.start();
    }
}
只截取主要源码

创建Thread传入Runnable实例(其实现接口子类,多态),初始化target。Thread调用start本质还是调用实现接口的MyRunnable的run方法

代码语言:javascript
代码运行次数:0
运行
复制
private Runnable target;
public Thread(Runnable target) {
    this(null, target, "Thread-" + nextThreadNum(), 0);
}
@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

六、线程的生命周期

  • 新建: 当一个Thread类或子类的对象被声明并创建时,新生成的线程对象处于新建状态
  • 就绪: 处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它具备了运行的条件,只是没分配到CUP资源
  • 运行: 当就绪的线程被调度并获得CPU资源时,便进入运行状态,run()方法定义了线程的操作和功能
  • 阻塞: 在某种特殊情况下,被认为挂起或执行输入输出操作时,让出CPU并临时中止自己的执行,进入阻塞状态
  • 死亡: 线程完成了它的全部工作或线程被提前强制性中止或出现异常

七、线程的同步

举个卖票栗子:

代码语言:javascript
代码运行次数:0
运行
复制
class TicketsRunnable implements Runnable{
    private int ticket = 10;
    @Override
    public void run() {
        while (true){
            if(ticket > 0){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":卖出票号:"+ticket);
            }else {
                break;
            }
            ticket--;
        }

    }
}
public class SellingTicketsTest {
    public static void main(String[] args) {
        TicketsRunnable runnable = new TicketsRunnable();
        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        Thread t3 = new Thread(runnable);
        Thread t4 = new Thread(runnable);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t4.setName("窗口4");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
结果:
窗口1:卖出票号:10
窗口4:卖出票号:10
窗口3:卖出票号:10
窗口2:卖出票号:10
窗口2:卖出票号:6
窗口4:卖出票号:6
窗口3:卖出票号:6
窗口1:卖出票号:5
窗口2:卖出票号:2
窗口4:卖出票号:2
窗口1:卖出票号:2
窗口3:卖出票号:2
窗口2:卖出票号:-2

说明:run方法中睡眠了1秒,四个线程开启后,因为运行速度快,四个线程会依次进入睡眠,然后再票号-1前同时打印售出票10号,所以都是10。当票号还有2张时候,四个线程同上依次进入睡眠,然后同时打印出票2号,然后一个线程-1,票号为1,会进入下一次循环。同时其他三个线程-1,这时候票号为-2,这三个线程根据票号>0,也进入不了循环。那个进入循环的打印票号-2。

  • 同步代码块

synchronized(同步监视器){ //需要被同步的代码 }

  1. 操作共享数据的代码,即为需要被同步的代码
  2. 共享数据:多个线程同时操作的变量
  3. 同步监视器,俗称:锁。任何一个类的对象,都可以充当锁
代码语言:javascript
代码运行次数:0
运行
复制
class TicketsRunnable implements Runnable{
    private int ticket = 10;
    final Object obj = new Object();
    @Override
    public void run() {
        while (true){
            //方式一:TicketsRunnable 只创建了一次,故obj对象只有一个
//            synchronized (obj){
            //方式二:TicketsRunnable.class 为 Class对象,只有一个
//            synchronized (TicketsRunnable.class){
            //方式三:TicketsRunnable 只创建了一次,故TicketsRunnable的对象也只有一个,this也只有一个
            synchronized (this){
                if(ticket > 0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":卖出票号:"+ticket);
                }else {
                    break;
                }
                ticket--;
            }
        }

    }
}

public class SellingTicketsTest {
    public static void main(String[] args) {
        TicketsRunnable runnable = new TicketsRunnable();
        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        Thread t3 = new Thread(runnable);
        Thread t4 = new Thread(runnable);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t4.setName("窗口4");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
结果:
窗口1:卖出票号:10
窗口1:卖出票号:9
窗口1:卖出票号:8
窗口1:卖出票号:7
窗口1:卖出票号:6
窗口1:卖出票号:5
窗口1:卖出票号:4
窗口3:卖出票号:3
窗口3:卖出票号:2
窗口4:卖出票号:1
  1. 方式一 synchronized (obj):TicketsRunnable 只创建了一次,故obj对象只有一个
  2. 方式二synchronized (TicketsRunnable.class):TicketsRunnable.class 为Class对象,只有一个 (继承Thread类,会创建多个类,但只要一个Class对象)
  3. 方式三synchronized (this):TicketsRunnable 只创建了一次,故TicketsRunnable的对象也只有一个,this也只有一个(实现Runnable接口,只会创建一次)
  • 同步方法

如果操作共享数据的代码完整的声明在一个方法中,可以将此方法声明为同步的。

实现Runnable接口:

代码语言:javascript
代码运行次数:0
运行
复制
class TicketsRunnable implements Runnable{
    private int ticket = 10;
    @Override
    public void run() {
        while (true){
            show();
            if (ticket < 0) {
                break;
            }
        }
    }
    private synchronized void show(){//同步监视器:this 
        if(ticket > 0){
            System.out.println(Thread.currentThread().getName() + ":卖出票号:"+ticket);
        }
        ticket--;
    }
}
public class SellingTicketsTest {
    public static void main(String[] args) {
        TicketsRunnable runnable = new TicketsRunnable();
        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        Thread t3 = new Thread(runnable);
        Thread t4 = new Thread(runnable);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t4.setName("窗口4");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

继承Thread类:

代码语言:javascript
代码运行次数:0
运行
复制
class TicketsThread extends Thread{
    private static int ticket = 10;//静态,创建多个TicketsThread对象,其只有一个共享
    @Override
    public void run() {
        while (true){
            show();
            if (ticket < 0) {
                break;
            }
        }
    }
    private static synchronized void show(){//同步监视器:TicketsThread类本身及Class对象,唯一的
        if(ticket > 0){
            System.out.println(Thread.currentThread().getName() + ":卖出票号:"+ticket);
        }
        ticket--;
    }
}
public class SellingTicketsTest1 {
    public static void main(String[] args) {
        TicketsThread t1 = new TicketsThread();
        TicketsThread t2 = new TicketsThread();
        TicketsThread t3 = new TicketsThread();
        TicketsThread t4 = new TicketsThread();
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t4.setName("窗口4");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

总结:

  1. 同步方法仍然涉及同步监视器,只是不需要显式的声明。
  2. 非静态的同步方法,同步监视器是:this
  3. 静态的同步方法,同步监视器是:当前类,Class对象

八、死锁

  • 不同的线程分别占用对方需要的资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程死锁。
  • 出现死锁后,不会出现异常,不会出现提示,只是所有线程都处于阻塞状态,无法继续
代码语言:javascript
代码运行次数:0
运行
复制
public class Deadlock {
    public static void main(String[] args) {
        StringBuilder s1 = new StringBuilder("a");
        StringBuilder s2 = new StringBuilder("1");
        //线程一:
        new Thread(){
            @Override
            public void run() {
                synchronized (s1){
                    s1.append("b");
                    s2.append("2");
                    System.out.println("s1外: s1="+s1+"-----s2="+s2);
                    synchronized (s2){
                        s1.append("c");
                        s2.append("3");
                        System.out.println("s2内: s1="+s1+"-----s2="+s2);
                    }
                }
            }
        }.start();
        //线程二:
        new Thread(() -> {
            synchronized (s2){
                s1.append("b");
                s2.append("2");
                System.out.println("s2外: s1="+s1+"-----s2="+s2);
                synchronized (s1){
                    s1.append("c");
                    s2.append("3");
                    System.out.println("s1内: s1="+s1+"-----s2="+s2);
                }
            }
        }).start();
    }
}
结果:
s2外: s1=abb-----s2=122
s1外: s1=abb-----s2=122

两个线程都进入不到内层同步代码块中,因为此时双方拿着对方需要的锁(对象),等待对方释放,一直处于僵持阶段。

九、Lock(锁)

  • Lock接口是控制多个线程对共享资源进行访问的工具。
  • ReentrantLock类实现了Lock,可以显式加锁和释放锁。

ReentrantLock lock = new ReentrantLock(true);//true为公平锁(线程先进来就先获取锁),默认false。

代码语言:javascript
代码运行次数:0
运行
复制
class LockRunnable implements Runnable{
    private int tickets = 10;
    //1.创建锁
    private ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true){
            try {
                //2.调用锁定方法lock()
                lock.lock();
                if (tickets > 0) {
                    System.out.println(Thread.currentThread().getName() + "  售出票号:" + tickets);
                    tickets--;
                } else {
                    break;
                }
            }finally {
                //3.调用解锁方法unlock()
                lock.unlock();
            }
        }
    }
}
public class LockTest {
    public static void main(String[] args) {
        LockRunnable runnable = new LockRunnable();
        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t1.start();
        t2.start();
    }
}
结果:
窗口1  售出票号:10
窗口1  售出票号:9
窗口2  售出票号:8
窗口1  售出票号:7
窗口2  售出票号:6
窗口1  售出票号:5
窗口1  售出票号:4
窗口1  售出票号:3
窗口1  售出票号:2
窗口1  售出票号:1

synchronized 与 Lock的区别

  1. Lock是显式锁(手动开启和关闭锁,别忘记关闭锁),synchronized是隐式锁,出了作用域自动释放
  2. Lock只有代码块锁,synchronized有代码块锁和方法锁
  3. 使用Lock锁,JVM花费较少时间调度线程,性能更好;也比较灵活。
  4. 优先使用顺序:Lock --> 同步代码块 --> 同步方法

十、线程的通信

使用两个线程打印1-10。线程1,线程2交替打印

代码语言:javascript
代码运行次数:0
运行
复制
class PrintRunnable implements Runnable{
    private int num = 10;
    @Override
    public void run() {
        while (true){
            synchronized (this){
                this.notify();
                if (num > 0){
                    System.out.println(Thread.currentThread().getName() + ": 数字"+num);
                    num--;
                }else {
                    break;
                }
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
public class PrintThread {
    public static void main(String[] args) {
        PrintRunnable runnable = new PrintRunnable();
        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        t1.setName("线程1");
        t2.setName("线程2");
        t1.start();
        t2.start();
    }
}
结果:
线程1: 数字10
线程2: 数字9
线程1: 数字8
线程2: 数字7
线程1: 数字6
线程2: 数字5
线程1: 数字4
线程2: 数字3
线程1: 数字2
线程2: 数字1

线程1进入同步代码块,通过notify方法,没有等待线程。直接打印,然后走到wait,阻塞,并释放锁。 线程2进入同步代码块,通过notify方法唤醒线程1,线程1处于就绪状态(锁在线程2手里)。直到线程2打印,然后走到wait,阻塞,释放锁,线程1开始接着wait后面继续执行。开始循环。 这样线程1、2就交替打印了。

涉及到的三个方法:
  • wait():执行此方法,当前线程进入阻塞状态,并释放锁(同步监视器)
  • notify():执行此方法,唤醒被wait的一个线程,此线程进入就绪状态。 如果多个线程被wait,唤醒优先级高的、随机唤醒
  • notityAll():执行此方法,唤醒所有被wait的线程
说明:
  • 三个方法必须使用在同步代码块或同步方法中
  • 三个方法的调用者必须是同步代码块或同步方法的同步监视器的对象,否则,报错。
  • 三个方法定义在java.lang.Object类中

十一、实现Callable接口创建线程

  • call()可以有返回值
  • call()可以抛出异常
  • Callable支持泛型
代码语言:javascript
代码运行次数:0
运行
复制
//1.创建一个实现Callable的实现类
class CallableThread implements Callable<Integer>{
    //2.实现call方法,将此线程需要执行的操作声明在call中
    @Override
    public Integer call() throws Exception {
        int num = 0;
        for (int i = 1; i <= 10; i++) {
            num += i;
        }
        return num;
    }
}
public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //3.创建Callable接口实现类的对象
        CallableThread callableThread = new CallableThread();
        //4.将此Callable接口实现类的对象传入FutureTask的构造器中,创建FutureTask对象
        FutureTask<Integer> futureTask = new FutureTask<>(callableThread);
        //5.将Future对象传入Thread构造器中,创建此线程
        Thread t1 = new Thread(futureTask);
        t1.start();
        //get返回值即为Callable实现类重写call方法的返回值(没有返回值则不调用)
        Integer num = futureTask.get();
        System.out.println(num);
    }
}

十二、使用线程池创建线程

  • 提高响应速度(减少了创建新线程的时间)
  • 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
  • 便于线程管理 ①corePoolSize:核心池的大小 ②maximumPoolSize:最大线程数 ③keepAliveTime:线程没有任务时,最多保持多久后终止
线程池API:
  • ExecutorService:线程池接口。常用子类ThreadPoolExecutor ①void execute(Runnable command):没有返回值,一般用来执行Runnable ②Future submit(Callable task):有返回值,一般用来执行Callable ③void shutdow():关闭连接池
  • Executors:工具类、线程池的工具类,用来创建并返回不同类型线程池 ①Executors.newCachedThreadPool():创建一个可根据需要创建新线程的线程池 ②Executors.newFixedThreadPool(n):创建一个可重用固定线程数的线程池 ③Executors.newSingleThreadExecutor():创建一个只有一个线程的线程池 ④Executors.newScheduledThreadPool(n):创建一个线程池,它可安排在给定延迟后运行命令或者定期的执行。
代码语言:javascript
代码运行次数:0
运行
复制
class ThreadExecutor implements Runnable{
    @Override
    public void run() {
        System.out.println("执行方法");
    }
}
public class ThreadPool {
    public static void main(String[] args) {
        //1.提供指定线程数的线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        //设置属性
        ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) service;
//        poolExecutor.setCorePoolSize();
//        poolExecutor.setMaximumPoolSize();
        //2.执行指定的线程操作(Runnable)
        service.execute(new ThreadExecutor());
//        service.submit(Callable task)
        //3.关闭连接池
        service.shutdown();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、基础概念:程序、进程、线程
  • 二、继承Thread:多线程的创建和使用
    • 快捷方式创建:
  • 三、Thread的常用方法
  • 四、线程的调度
  • 五、实现Runnable:多线程的创建和使用
    • 只截取主要源码
  • 六、线程的生命周期
  • 七、线程的同步
  • 八、死锁
  • 九、Lock(锁)
  • 十、线程的通信
    • 涉及到的三个方法:
    • 说明:
  • 十一、实现Callable接口创建线程
  • 十二、使用线程池创建线程
    • 线程池API:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档