初谈多线程

多线程的使用可以让我们充分利用cpu的资源,提高cpu的使用效率,采用多线程同时完成多个任务,而不互相干扰。

初谈多线程

(1)什么是并发,并行

并发:指两个或多个事件在同一时刻发生(同时发生)。

并行:指两个或多个事件在同一个时间段内发生。

这里我们把我们所说的高并发混在一起,高并发意味着单位时间内系统能处理的请求数很高,我们通过一定的技术手段解决问题

(2)进程和线程

**进程:**我们正在运行的程序实例,进程是线程的容器,一个进程可以有多个线程。

**线程:**线程是进程内部的一个独立执行单元,是进程的最小单位。

(3)java线程的创建

在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。

1、线程的创建方式

1、继承Thread类
2、实现Runnable接口
3、实现Callable接口
4、线程池

Runnable和Callable接口比较:

相同点:

1、两者都是接口;
2、两者都可用来编写多线程程序;
3、两者都需要调用Thread.start()启动线程;

不同点:

1、实现Callable接口的线程能返回执行结果;而实现Runnable接口的线程不能返回结果;
2、Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的不允许抛异常;
3、实现Callable接口的线程可以调用Future.cancel取消执行 ,而实现Runnable接口的线程不能

2、线程池的使用

  • 线程的创建时很消耗资源的,无限的创建线程是会产生内存溢出的,所以线程池的使用是很好的解决方案。

  • Executors 工具类的不同方法按照我们的需求创建了不同的线程池,来满足业务的需求。

  • 使用 ThreadPoolExecutor 可以创建自定义线程池

《阿里巴巴Java开发手册》线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

Executors 各个方法的弊端:

  • newFixedThreadPool 和 newSingleThreadExecutor:
    主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至 OOM。
  • newCachedThreadPool 和 newScheduledThreadPool:
    主要问题是线程数最大数是 Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至 OOM。

我们可以了解一下ThreadPoolExecutor 的使用

ThreadPoolExecutor3 个最重要的参数:

  • corePoolSize :核心线程数,线程数定义了最小可以同时运行的线程数量。
  • maximumPoolSize :线程池中允许存在的工作线程的最大数量
  • workQueue:当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,任务就会被存放在队列中。

ThreadPoolExecutor其他常见参数:

  • keepAliveTime:线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime才会被回收销毁;
  • unit :keepAliveTime 参数的时间单位。
  • threadFactor:为线程池提供创建新线程的线程工厂
  • handler :线程池任务队列超过 maxinumPoolSize 之后的拒绝策略

3、线程生命周期

(1)新建

1、new关键字创建了一个线程之后,该线程就处于新建状态
2、JVM为线程分配内存,初始化成员变量值

(2)就绪

1、当线程对象调用了start()方法之后,该线程处于就绪状态
2、JVM为线程创建方法栈和程序计数器,等待线程调度器调度

(3)运行

就绪状态的线程获得CPU资源,开始运行run()方法,该线程进入运行状态

(4)阻塞

当发生如下情况时,线程将会进入阻塞状态

1、线程调用sleep()方法主动放弃所占用的处理器资源
2、线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞
3、线程试图获得一个同步锁(同步监视器),但该同步锁正被其他线程所持有。
4、线程在等待某个通知notify
5、程序调用了线程的suspend()方法将该线程挂起。但这个方法容易导致死锁,所以应该尽量避免使用该方法

(5)死亡

线程会以如下3种方式结束,结束后就处于死亡状态:

1、run()或call()方法执行完成,线程正常结束。
2、线程抛出一个未捕获的Exception或Error。
3、调用该线程stop()方法来结束该线程,该方法容易导致死锁,不推荐使用。

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×