JAVA学习笔记之线程拓展 - 线程池

一、使用线程池的原因

不使用线程池出现的问题:

如果不使用线程池,那么每次需要用的时候就需要创建一个线程,等待线程执行完之后,线程销毁,乍一看没什么问题,但是当并发量足够高的时候,系统就需要花费大量的时候来创建和销毁线程,降低了系统的效率;

什么是线程池:

线程池就是一个用来存放线程的容器

线程池原理:
程序启动的时候创建一定数量的线程放到线程池中,当有需要的时候,就从容器中拿出线程来执行任务,任务执行结束,在放回容器中,复用线程,这样就避免频繁的创建和销毁线程;

线程池的好处:

1.减少资源的消耗
2.提高程序的响应速度
3.提高线程的可管理性

二、线程池-Runnable任务

如何创建线程池:

通过工具类Executors的静态方法

//传入的参数是你要创建的线程数
Executors.newFixedThreadPool(2);

Executors常用方法:

Future submit(Runnable r)
提交Runnable任务

提交Runnable步骤:

1.创建线程池,并指定数量

2.创建类实现runnable接口,重写run方法

3.调用submit方法提交实现runnable的类对象

代码样例:

public class PoleTest {
    public static void main(String[] args) {
        //创建线程池,指定线程数量
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //创建实现runnable接口的对象
        RunTh th = new RunTh();
        //提交任务给线程池
        pool.submit(th);
        pool.submit(th);
    }
}

public class RunTh implements Runnable {
    public void run() {
        System.out.println("正在运行"+"\t" + Thread.currentThread().getName());
    }
}

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

在这里插入图片描述

三、线程池-Callable任务

什么是callable接口:

接口方法:

public V call() throws Exception;

提交Callable任务步骤:

1.创建线程池对象,并指定线程数

2.创建类实现callable方法,并重写call方法(和Runnable中的run方法一样,都是存放线程代码)

3.3.调用submit方法提交实现callable的类对象

代码样例:

public class PoleTest {
    public static void main(String[] args) {
        //创建线程池,指定线程数量
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //创建实现callable接口的对象
        CallTh callTh = new CallTh();
        //提交任务给线程池
        pool.submit(callTh);
        pool.submit(callTh);
    }
}

//由于是泛型类所以随便指定一种类型
public class CallTh implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("正在运行" + "\t" + Thread.currentThread().getName());
        return "abc";
    }
}

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

Callable接口的好处:

1.任务执行结束有返回值

2.方法上可以声明异常

所以,如果需要返回值或需要声明异常,就选Callable接口,否则两个都可以选择;

Callable获取返回值:

Future<T> submit (Callable task) ;
//提交callable任务并返回一个Future对象
    
T get();
//获得callable任务的返回值
线程池常用方法作用
Future submit (Callable task)提交Callable任务
Future submit (Runnable task) ;提交Runnable任务
void shutdown();等待线程池中的任务结束销毁线程池
void shutdownNow();立即销毁线程池,不会等待线程池中执行的任务

线程池实现多数求和:

public class PoleTest {
    public static void main(String[] args) throws Exception {
        //创建线程池
        ExecutorService pool = Executors.newFixedThreadPool(2);
        //循环获得前30个数的和
        for (int i = 1; i <= 30; i++) {
            SumNum num = new SumNum(i);
            Future<Integer> submit = pool.submit(num);
            System.out.println("前" + i + "个数的和是:" + submit.get());
        }
        //销毁线程池
        pool.shutdown();
    }
}

public class SumNum implements Callable<Integer> {
    public int n ;
    //接收要求前几个数的和
    public SumNum(int n) {
        this.n = n;
    }
    @Override
    public Integer call() throws Exception {
        System.out.println("这是"+Thread.currentThread().getName()
        +"线程,在执行前"+n+"个数求和计算!");
        int sum = 0;
        for (int i = 0; i <= n; i++) {
            sum += i;
        }
        return sum;
    }
}

四、线程死锁

什么是死锁:

多个线程在执行过程中,因为抢占资源而出现的相互等待现象称为死锁;

死锁的条件:

1.多个线程

2.多个锁对象

3.同步代码块的嵌套

如何避免死锁:

1.使用单线程

2.使用一把锁

3.不用同步代码块嵌套

线程更多相关内容,请移步上篇文章:JAVA学习笔记之线程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值