1. 进程:由线程组成。
线程是进程中的一部分,进程包含多个线程在运行。
2. 并行与并发
并行:在同一时刻,有多条指令在多个处理器上同时执行
并发:在同一时刻只有一条指令执行,但是多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。
现在的操作系统都支持多进程的并发。
3. 线程、进程
多线程是拓展了多进程的概念。使得一个进程可以处理多个任务。
线程(Thread)被称为轻量级进程。线程是进程的执行单元。
线程可以拥有自己的堆栈、自己的程序计数器和自己的局部变量,但不拥有系统资源。
与父进程的其他线程共享该进程所拥有的全部资源。
线程的执行时抢占式的。
4. 多线程编程的优点:
1)进程之间不能共享内存,但线程之间共享内存非常容易
2)系统创建则代价小得多,因此使用多线程来实现多任务并发比多进程的效率高。
3)Java语言内置了多线程功能支持,而不是单纯的作为底层操作系统的调度方式,从而简化了Java的多线程编程
5. 多线程的应用:
一个浏览器必须能同时下载多个图片
一个web服务器必须能同时响应多个用户请求;
Java虚拟机在后台提供了一个超级线程来进行垃圾回收;
图形用户界面(GUI)应用也需要启动单独的线程从主机环境用户界面事件
6. 线程的创建和启动
继承Thread类创建线程类
a) 定义Thread类的子类,并重写该类的run()方法,run()方法被称为线程执行体
b) 创建子类的实例,即创建了线程对象
c) 调用线程对象的start()方法来启动该线程
7. Volatile 关键字 为实例域的同步访问提供了一种免锁机制。
如果声明一个域为volatile,那么编译器和虚拟机就知道该域是可能被另一个线程并发更新的。
8. 线程池: 关闭 shutdown
构建一个新的线程是有一定的代价的。
如果程序中创建了大量生命期很短的线程,应该使用线程池(thread pool)。
一个线程池中包含许多准备运行的空闲进程。把Runnable对象交给线程池,就会有一个线程调用run方法。
当run方法退出时,线程不会死亡,而是在池中准备为下一个请求提供服务。
使用线程池可以减少并发线程的数目。
如果有一个算法会创建许多线程,应该使用线程数固定的线程池以限制并发线程的总数。
9. sleep wait
wait
wait()是属于Object类的方法。wait()方法可以做到如下几点:
(1)首先,调用了wait()之后会引起当前线程处于等待状状态。
(2)其次,每个线程必须持有该对象的monitor。如果在当前线程中调用wait()方法之后,该线程就会释放monitor的持有对象并让自己处于等待状态。
(3)如果想唤醒一个正在等待的线程,那么需要开启一个线程通过notify()或者notifyAll()方法去通知正在等待的线程获取monitor对象。如此,该线程即可打破等待的状态继续执行代码。
sleep
sleep()方法来自于Thread类。sleep()方法可以做到如下几点:
(1)首先,调用sleep()之后,会引起当前执行的线程进入暂时中断状态,也即睡眠状态。
(2)其次,虽然当前线程进入了睡眠状态,但是依然持有monitor对象。
(3)在中断完成之后,自动进入唤醒状态从而继续执行代码。
总结:
那么从以上的理论和实践来分析,我们能得出如下结论:
(1)在线程的运行过程中,调用该线程持有monitor对象的wait()方法时,该线程首先会进入等待状态,并将自己持有的monitor对象释放。
(2)如果一个线程正处于等待状态时,那么唤醒它的办法就是开启一个新的线程,通过notify()或者notifyAll()的方式去唤醒。当然,需要注意的一点就是,必须是同一个monitor对象。
(3)sleep()方法虽然会使线程中断,但是不会将自己的monitor对象释放,在中断结束后,依然能够保持代码继续执行。
10. notify notifyAll
notify()
(1)当一个线程处于wait()状态时,也即等待它之前所持有的object's monitor被释放,通过notify()方法可以让该线程重新处于活动状态,从而去抢夺object's monitor,唤醒该线程。
(2)如果多个线程同时处于等待状态,那么调用notify()方法只能随机唤醒一个线程。
(3)在同一时间内,只有一个线程能够获得object's monitor,执行完毕之后,则再将其释放供其它线程抢占。
notifyAll()就是用来唤醒正在等待状态中的所有线程的,不过也需要注意以下几点:
(1)notifyAll()只会唤醒那些等待抢占指定object's monitor的线程,其他线程则不会被唤醒。
(2)notifyAll()只会一个一个的唤醒,而并非统一唤醒。因为在同一时间内,只有一个线程能够持有object's monitor
(3)notifyAll()只是随机的唤醒线程,并非有序唤醒。