1.单线程和多线程区别
1.单线程:
(1)在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行
(2)系统稳定、扩展性极强、软件丰富,多用于点对点的服务
(3)同步应用程序的开发比较容易,效率通常比多线程应用程序低
(4)完成同步任务所用的时间比预计时间长,应用程序可能会不响应
举例:如果要同时做多件事情(理发,逛街,吃饭),只能一件一件去做,特别耗时间
2.多线程:
(1)使用多线程的理由之一是和进程相比,它是一种非常花销小,切换快,更"节俭"的多任务操作方式
(2)Java 给多线程编程提供了内置的支持
(3)一个进程中可以并发多个线程,每条线程并行执行不同的任务
(4)多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销,提升性能
(5)多线程能满足编写高效率的程序来达到充分利用 CPU 的目的
举例:同样是做多件事情(理发,逛街,吃饭),可以同时进行(相当分身了,分了3份),本来一天要做的事情,现在半天就可以
2.线程和进程的区别
1.线程:
(1)线程是一个动态执行的过程,它也有一个从产生到死亡的过程
(2)一个线程不能独立的存在,它必须是进程的一部分
(3)创建线程代价很小
2.进程:
(1)一个进程包括由操作系统分配的内存空间,包含一个或多个线程
(2)一个进程一直运行,直到所有的非守护线程都结束运行后才能结束
(3)创建进程代价很大
举例:(1)进程就相当于一条高速路,创建进程相当于从新修一条高速路;
(2)线程就相当于高速路上的车道(2,3,4车道等),创建线程相当于从新添加一个车道
3.守护线程和非守护线程
1.守护线程(Daemon Thread):和主线程一起结束的线程,叫守护线程
(1)也叫精灵线程, 当程序只剩下 守护线程的时候 程序就会退出
(2)作用 类似在后台静默执行 , 比如JVM的垃圾回收机制, 这个就是一个 守护线程
(3)是运行在后台的线程
(4)它是为非守护线程服务的线程
2.非守护线程(User Thread):主线程的结束不影响线程的执行的线程
(1)也叫用户线程
(2)JVM虚拟机正常退出的时机就是系统中不存在非守护线程的时候,也就是说系统中不存在普通线程时虚拟机退出而不管守护线程是否还在运行
(3)只要有任何非守护线程在运行,程序就不会终止
注:一般程序中用到的都是守护线程
4.线程的生命周期:(5个阶段)
(1)新建状态::使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。保持这个状 态直到程序 start() 这个线程
(2)就绪状态:当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度
(3)运行状态:执行 run(),此时线程便处于运行状态,处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
(4)阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态
1.在睡眠时间已到或获得设备资源后可以重新进入就绪状态(阻塞状态分三种)
2.等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态
3.同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)
4.其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态
(5)死亡状态:一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状
5.线程的优先级
(1)每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序
(2)具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源
6.创建一个线程(4种方式):后面详细介绍
(1)通过实现 Runnable 接口
(2)通过继承 Thread 类本身
(3)通过 Callable 和 Future 创建线程
(4)使用线程池例如用Executor框架
7.多线程的几个主要概念;
1.同步和异步:都是形容一次方法的调用
(1)线程同步:调用者必须要等到调用的方法返回后才会继续后续的行为
(2)线程异步:调用者调用后,不必等调用方法返回就可以继续后续的行为
2.并发和并行:形容多个任务时的状态
(1)多个任务交替运行
(2)多个任务同时运行
这两个概念的的区别就是一个是交替,另一个是同时。
如果只有一个 CPU 的话,系统是不可能并行执行任务,只能并发,因为 CPU 每次只能执行一条指令;
要实现并行,就需要多个 CPU;
3.可见性:一个线程修改了共享变量的值,其他线程能够立即得知这个修改
4.重排序:编译器和处理器为了优化程序性能而对指令重新排序的一种手段
5.有序性:是指程序的运行顺序与编写代码的顺序一致
6.线程安全:指某个方法在多线程环境被调用的时候,能够正确处理多个线程之间的共享变量,使程序功能能够正确执行
典型应用:窗口买票功能!(后面展示示例)
7.线程间通信:目标是使线程间能够互相发送信号
(1)正常情况下,每个子线程完成各自的任务就可以结束了
(2)线程通信使线程能够等待其他线程的信号
(3)有的时候,希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了
(4)用到机制:synchronized关键字、volatile关键字以及等待/通知(wait/notify/notifyAll)机制,管道输入/输出流、Thread.join()、 ThreadLocal
wait():
<1>调用wait()方法可以使调用该方法的线程释放共享资源的锁,然后从运行态退出,进入等待队列,直到被再次唤醒
<2>在调用wait()方法时,需要将它放入try…catch代码块中
<3>使用该方法时还需要把它放到一个同步代码段中
notify():
<1>可以唤醒等待队列中第一个等待同一共享资源的线程,并使该线程退出等待队列,进入可运行态
notifyAll():
<1>可以使所有正在等待队列中等待同一共享资源的线程从等待状态退出,进入可运行状态
<2>优先级最高的那个线程最先执行
8.线程死锁:
(1)当两个或多个线程正在等待彼此释放所需的资源并陷入无限等待时,这种情况称为死锁
(2)只会发生在多任务或者多线程的情况下
9.线程控制:挂起、停止和恢复
(1)isAlive:该方法用来测试线程是否处于活动状态,线程由start方法启动后,直至被终止之间的任何时刻都处于Alive状态。
当处于新建状态和死亡状态时,该方法返回false
(2)currentThread:该方法是Thread类的的类方法,返回正在使用CPU资源的线程
(3)interrupt:当线程处于休眠状态时,一个占有CPU资源的线程可以让休眠的线程调用interrupt方法唤醒自己,
导致休眠的线程发生InterruptedException异常结束休眠,重新排队等待CPU资源
(4)还有start、run、sleep方法
8.实现线程安全的方式
(1)synchronized 修饰符
语法格式
synchronized(obj) {
// 同步代码块
}
(2)synchronized 方法
语法格式
[修饰符] synchronized [返回值] [方法名](形参...) {
}
9.线程的核心知识:主要就两点
(1)线程同步;
(2)线程通讯(生产者----消费者模式)