Java_多线程

ch16_多线程

github源码参考: github jackaroo2020

16.1 线程概述

1.进程三个特性

  • 独立性:每个进程拥有自己独立的私有地址空间。
  • 动态性:是一个正在系统中活动的指令集合。
  • 并发性:可以在单个处理器上并发执行,多个进程之间不会相互影响。(并发指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得宏观上具有多个进程同时执行的效果。

2.操作系统可以执行多个任务,每个任务就是进程;进程可以同时执行多个任务,每个任务就是线程。

3.多线程优点

  • 进程不可以共享内存,但线程之间共享内存非常容易。
  • 系统创建进程时需要为该进程重新分配系统资源,但创建线程则代价小得多,因此使用多线程实现多任务并发比多进程效率高。
  • java语言内置多线程功能支持,简化编程。

16.2 多线程的创建和启动

1.继承Thread类创建线程类
2.实现Runable接口创建线程类
3.使用Callable和Future创建线程
4.创建三种方式的对比

notice:

  • java程序运行默认的主线程,main方法的方法体就是主线程的线程执行体。
  • 使用继承Thread类的方法来创建线程类时,多个线程之间无法共享线程类的实例变量。
  • 一般推荐使用实现Runable接口,Callable接口的方式来创建多线程。

16.3 线程的生命周期

1.新建(new)和就绪状态(start)
2.运行(run) 和阻塞状态
3.线程死亡
Java_多线程

notice:

  • 不要对处于死亡状态的线程调用start()方法,否则会引发IllegalThreadStateException异常。

16.4 控制线程

1.join线程
2.后台线程
3.线程睡眠
4.线程让步
5.改变线程的优先级

16.5 线程同步

1.线程安全问题
2.同步代码块
3.同步方法
4.同步锁(lock)
5.死锁

16.6 线程通信

1.传统的线程通信 synchronized wait() notify() notifyAll()
2.使用Condition控制线程通信 Lock await() signal() signalAll()
3.使用阻塞队列控制线程通信

16.7 线程组与未处理的异常

16.8 线程池

  • newCachedThreadPool()
  • newFixedThreadPool()
  • newSingleThreadExecutor()
  • newScheduledThreadpool(int corePoolSize)
  • newSingleThreadScheduledExecutor()
  • newWorkStealingPool()

调用线程池执行线程任务的步骤:
1)调用Executor类的静态工厂方法穿件一个ExecutorService对象,该对象代表一个线程池。
2)创建Runnable实现类或Callable实现类的实例,作为线程执行的任务。
3)调用ExecutorService对象的submit()方法来提交Runnable实例或Callable实例。
4)当不想提交任务任务时,调用ExecutorService对象的shutdown()方法来关闭线程池。

16.9 线程相关类

1)ThreadLocal类
就是为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本;而不会和其他线程的副本冲突。

ThreadLocal并不能替代同步机制,两者面向的问题领域不同。同步机制是 为了同步多个线程对相同资源的并发访问,是多个线程之间进行通信的有效方式;
ThreadLocal是为了隔离多个线程的数据共享,从根本上避免多个线程之间对共享资源(变量)的竞争,也就不需要对多个线程进行同步了。

建议:如果多个线程之间需要共享资源,以达到线程之间的通信功能,就使用同步机制;
如果需要隔离多个线程之间的共享冲突,则可以使用ThreadLocal。

2)包装线程不安全的集合类
Collections提供的类方法吧这些集合可以包装成线程安全的集合。

HashMap m = Collections.synchronizedMap(new HashMap());

3)线程安全的集合类

  • 以Concurent开头的集合类,如ConcurrentHashMap、ConcurrentLinkedQueue
  • 以CopyOnWrite开头的集合类,如CopyOnWriteArrayList(适合用在读取操作远远大于写入操作的场景中,如缓存等)、CopyOnwriteArraySet