一. 线程
1. 什么是线程:
线程是进程的一个实体, 是 CPU 调度和分派的基本单位, 它是比进程更小的能独立运行的基本单位. 一个进程至少包含一个线程, 也可以多个, 线程属于进程.
2.Java 中线程经历的四个过程:
(1)创建:
创建一个 Java 线程常见的有两种方式: 继承 Thread 类和实现 Runnable 接口这两种方式.
(2)执行:
线程创建后仅仅占有了内存资源, 在 JVM 管理的线程中还没有该线程, 该线程必须调用 start 方法通知 JVM, 这样 JVM 就会知道又有一个新的线程排队等候了. 如果当前线程轮到了 CPU 的使用权限的话, 当前线程就会继续执行.
(3)中断:
a.JVM 将 CPU 的使用权限从当前线程切换到其它线程, 使本线程让出 CPU 的使用权限而处于中断状态.
b. 线程在执行过程中调用了 sleep 方法, 使当前线程处于休眠状态.
c. 线程在执行的过程中调用 wait 方法
d. 线程在使用 CPU 资源期间, 执行了某个操作而进如阻塞状态.
(4)死亡
死亡的线程不在具有执行能力. 线程死亡的原因有二:
a. 线程正常运行结束而引起的死亡, 即 run 方法执行完毕.
b. 线程被提前强制终止.
3.Thread 类:
3.1 构造方法:
3.2 常用方法:
3.3 相关方法使用:
(1)继承实现 Thread 类:
- package com.swpu.thread;
- class MyThread extends Thread{
- public MyThread(String name){
- super(name);
- }
- public void run(){
- for(int i=0;i<10;i++){
- System.out.println(getName()+"正在运行"+(i+1));
- }
- }
- }
- public class ThreadTest {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- MyThread mythread1=new MyThread("线程 1");
- MyThread mythread2=new MyThread("线程 2");
- mythread1.start();
- mythread2.start();
- }
- }
- View Code
(2)实现 Runnable 接口:
为什么要实现 Runnable 接口: Java 不支持多继承了不打算重写 Thread 类的其他方法.
- package com.swpu.thread;
- class PrintRunnable implements Runnable {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- for (int i = 1; i <10; i++) {
- System.out.println(Thread.currentThread().getName() + "正在运行"+(i++));
- }
- }
- }
- public class ThreadTest {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- // 如果都是使用的 pr1, 那就相当于资源共享
- PrintRunnable pr1 = new PrintRunnable();
- Thread th1 = new Thread(pr1);
- PrintRunnable pr2 = new PrintRunnable();
- Thread th2 = new Thread(pr2);
- th1.start();
- th2.start();
- }
- }
- View Code
3.4 线程的状态:
3.5 正在运行状态 ---->阻塞状态相关方法使用:
(1)sleep():
在指定的毫秒数内让正在执行的线程休眠(暂停执行), 参数是休眠的时间(毫秒).
使用场景: 定期刷新某项东西, 计时间等
- package com.swpu.thread;
- class PrintRunnable implements Runnable {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- for (int i = 1; i < 10;) {
- System.out.println(Thread.currentThread().getName() + "正在运行" + (i++));
- // 需要捕获异常(运行时退出)
- try {
- // 休眠时间结束后, 线程不会立即变成执行状态, 而是变成可执行状态, 需要获取 CPU 使用权才能变成执行状态
- // 因此时间需要多花一点
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- public class ThreadTest {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- // 如果都是使用的 pr1, 那就相当于资源共享
- PrintRunnable pr1 = new PrintRunnable();
- Thread th1 = new Thread(pr1);
- PrintRunnable pr2 = new PrintRunnable();
- Thread th2 = new Thread(pr2);
- th1.start();
- th2.start();
- }
- }
- View Code
- (2)join():
等待该方法的线程结束后才能执行. 也有个参数为毫秒, 等待线程终止的最长时间为多少毫秒(即在该线程执行的最长时间, 无论线程是否结束都会执行其他线程).
- package com.swpu;
- class MyThread extends Thread {
- public void run() {
- for (int i = 0; i < 10; i++) {
- System.out.println(getName() + "执行第" + (i + 1));
- }
- }
- }
- public class ThreadTest {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- MyThread mythread = new MyThread();
- mythread.start();
- try{
- // 抢占资源, 会等待 Thread-0 运行完成后, 其他线程才能执行
- mythread.join();
- }
- catch(InterruptedException e){
- e.printStackTrace();
- }
- for(int i=0;i<10;i++){
- System.out.println("主线程运行第"+(i+1));
- }
- }
- }
- View Code
3.6 线程优先级:(优先级的设置与操作系统及工作环境都有关)
Java 线程类提供 10 个优先级;
优先级可以用整个整数 1-10 表示, 超过范围会抛出异常;
主线程默认优先级为 5.
优先级常量: MAX_PRIORITY: 线程的最高优先级 10,MIN_PRIORITY: 线程的最低优先级 1,NORM_PRIORITY: 线程的默认优先级 5(主线程为 5)
优先级方法: getPriority()获得优先级, setPriority()设置优先级,
- package com.swpu;
- class MyThread extends Thread {
- public void run() {
- for(int i=0;i<50;i++){
- System.out.println(getName()+"运行完成"+(i+1));
- }
- }
- }
- public class ThreadTest {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- int mainPriority=Thread.currentThread().getPriority();
- System.out.println("主线程优先级为:"+mainPriority);
- MyThread mythread1 = new MyThread();
- MyThread mythread2 = new MyThread();
- // 设置两个线程的优先级
- mythread1.setPriority(Thread.MAX_PRIORITY);
- mythread2.setPriority(Thread.MIN_PRIORITY);
- mythread1.start();
- mythread2.start();
- }
- }
- View Code
4. 线程中的问题及线程同步:
各个线程是通过竞争 CPU 时间而获得运行时间的;
各 CPU 什么时候得到 CPU 时间, 占用多久, 是不可预测的;
一个正在运行的线程在什么地方被暂停是不确定的.
线程同步: synchronized 关键字用在成员方法, 静态方法, 语句块.[防止执行过程中语句未执行完整跳到另一个线程, 使取得的数据有误差]
5. 线程间通信:
wait(): 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前, 导致当前线程等待;
notify(): 唤醒在此对象监视器上等待的单个线程;
notifyAll(): 唤醒在此对象监视器上等待的所有线程.
例:
Queue:
- package com.swpu.queue;
- public class Queue {
- private int n;
- boolean flag=false;
- public synchronized int get() {
- if(!flag){
- try{
- wait();
- }
- catch(InterruptedException e){
- e.printStackTrace();
- }
- }
- System.out.println("获取:"+n);
- flag=false;// 消费完毕
- // 唤醒所有线程, notify()随机唤醒一个
- notifyAll();
- return n;
- }
- public synchronized void set(int n) {
- if(flag){
- try{
- wait();
- }
- catch(InterruptedException e){
- e.printStackTrace();
- }
- }
- System.out.println("设置:"+n);
- this.n = n;
- flag=true;// 容器中已经有数据
- notifyAll();
- }
- }
- View Code
- Producer:
- package com.swpu.queue;
- public class Producer implements Runnable{
- Queue queue;
- Producer(Queue queue){
- this.queue=queue;
- }
- @Override
- public void run() {
- int i=0;
- while(true){
- queue.set(i++);
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- View Code
- Consumer:
- package com.swpu.queue;
- public class Consumer implements Runnable {
- Queue queue;
- Consumer(Queue queue) {
- this.queue = queue;
- }
- @Override
- public void run() {
- while (true) {
- queue.get();
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- View Code
- Test:
- package com.swpu.queue;
- public class Test {
- public static void main(String[] args){
- Queue queue=new Queue();
- new Thread(new Producer(queue)).start();
- new Thread(new Consumer(queue)).start();
- }
- }
- View Code
6.Java 各种线程锁:
https://www.jianshu.com/p/fa084227c96b
二. 进程
1. 什么是进程:
进程是程序的一次动态执行, 它对应着从代码加载, 执行至执行完毕的一个完整的过程, 是一个动态的实体, 它有自己的生命周期. 它因创建而产生, 因调度而运行, 因等待资源或事件而被处于等待状态, 因完成任务而被撤消. 反映了一个程序在一定的数据 集上运行的全部动态过程. 通过进程控制块 (PCB) 唯一的标识某个进程. 同时进程占据着相应的资源(例如包括 CPU 的使用 , 轮转时间以及一些其它设备的权限). 是系统进行资源分配和调度的一个独立单位.
2. 程序:
一段静态的代码, 一组指令的有序集合, 它本身没有任何运行的含义, 它只是一个静态的实体, 是应用软件执行的蓝本.
3. 进程和程序的区别:
状态 | 是否具有资源 | 是否有唯一标识 | 是否具有并发性 | |
进程 | 动态 | √ | √ | √ |
程序 | 静态 | × | √ | × |
4. 进程的状态及转换:
(1)就绪 (Ready) 状态
当进程已分配到除 CPU 以外的所有必要资源后, 只要在获得 CPU, 便可立即执行, 进程这时的状态就称为就绪状态. 在一个系统中处于就绪状态的进程可能有多个, 通常将他们排成一个队列, 称为就绪队列.
(2)执行状态
进程已获得 CPU, 其程序正在执行. 在单处理机系统中, 只有一个进程处于执行状态; 再多处理机系统中, 则有多个进程处于执行状态.
(3)阻塞状态
正在执行的进程由于发生某事件而暂时无法继续执行时, 便放弃处理机而处于暂停状态, 亦即程序的执行受到阻塞, 把这种暂停状态称为阻塞状态, 有时也称为等待状态或封锁状态.
5. 多进程相关实现:
三. 相关参考
程序, 线程, 进程详解: https://www.cnblogs.com/xiohao/p/4310644.html
来源: http://www.bubuko.com/infodetail-3043017.html