线程 IO流 网络编程 基础总结
线程
进程---->进行中的程序
线程---->由进程创建 一个进程可以创建多个线程
并发:同一个时刻 多个任务交替执行 造成一种貌似同时进行的错觉 简单来说 单个cpu的多任务就是并发
并行:同一个时刻 多个任务同时执行 多个cpu可以实现并行
线程的基本使用
继承Thread类
实现Runnable接口
说明 Java是单继承机制 在某些情况下 一个类可能已经继承了某个父类 这时再用继承Thread类方法 来创建线程不可能 所以可以通过实现Runnable接口来创建线程
常用方法第二组
yield 线程的礼让 不一定成功
join 线程的插队 插队的线程一旦插队成功 则肯定先执行完插入的线程所有的任务
用户线程 也叫工作线程 当线程的任务执行完 或 通知方式结束
守护线程 一般是为工作线程服务的 当所有的用户线程结束 守护线程自动结束
常见的守护线程:垃圾回收机制
线程的生命周期
NEW 尚未启动的线程处于该状态
RUNNABLE 在Java虚拟机中执行的线程处于此状态 (READY RUNNING)
BLOCKED 在阻塞等待监视器锁定的线程处于此状态
WAITING 正在等待另一个线程执行特定动作的线程处于此状态
TIMED_WAITING正在等待另一个线程执行动作达到指定等待时间的线程处于该状态
TERMINATED 已退出的线程处于此状态
线程的同步
在多线程编程中 一些敏感数据不允许被多个线程同时访问 此时就使用同步访问计数 保证数据在任何同一时刻 最多有一个线程访问 以保证数据的完整性
理解 线程同步 即当有一个线程在对内存进行操作时 其他线程都不可以对这个内存地址进行操作 知道该线程完成操作 其他线程才能对该内存地址进行操作
同步具体方法
1. 同步代码块
synchronized(对象) {
得到对象的锁 才能操作同步代码
}
2.同步方法
public synchronized void m(String name) {
}
互斥锁
介绍
- Java中 引入对象互斥锁的概念 来保证共享数据操作的完整性
- 每个对象都对应了一个可称为"互斥锁"的标记 这个标记用来保证在任一时刻 只能有一个线程访问该对象
- 关键字synchronized来与对象的互斥锁联系 当某个对象用synchronized修饰时 表明该对象在任一时刻只能由一个线程访问
- 同步的局限性 导致程序的执行效率要降低
- 同步方法(非静态的)的锁可以是this 也可以是其他对象
- 同步方法(静态的) 的锁为当前类本身
同步方法如果没有使用static修饰 默认锁对象为this
如果方法使用static修饰 默认锁对象 当前类.class
线程的死锁
多个线程都占用了对方的锁资源 不肯礼让 导致了死锁
模拟线程死锁
点击查看代码
public class DeadLock_ {
public static void main(String[] args) {
DeadLockDemo A = new DeadLockDemo(true);
A.setName("A 线程");
DeadLockDemo B = new DeadLockDemo(false);
B.setName("B 线程");
A.start();
B.start();
}
}
@SuppressWarnings({"all"})
class DeadLockDemo extends Thread {
static Object o1 = new Object();// 保证多线程,共享一个对象,这里使用 static
static Object o2 = new Object();
boolean flag;
public DeadLockDemo(boolean flag) {//构造器
this.flag = flag;
}
@Override
public void run() {
//下面业务逻辑的分析
//1. 如果 flag 为 T, 线程 A 就会先得到/持有 o1 对象锁, 然后尝试去获取 o2 对象锁
//2. 如果线程 A 得不到 o2 对象锁,就会 Blocked
//3. 如果 flag 为 F, 线程 B 就会先得到/持有 o2 对象锁, 然后尝试去获取 o1 对象锁
//4. 如果线程 B 得不到 o1 对象锁,就会 Blocked
if (flag) {
synchronized (o1) {//对象互斥锁, 下面就是同步代码
System.out.println(Thread.currentThread().getName() + " 进入 1");
synchronized (o2) { // 这里获得 li 对象的监视权
System.out.println(Thread.currentThread().getName() + " 进入 2");
}
}
} else {
synchronized (o2) {
System.out.println(Thread.currentThread().getName() + " 进入 3");
synchronized (o1) { // 这里获得 li 对象的监视权
System.out.println(Thread.currentThread().getName() + " 进入 4");
}
}
}
}
释放锁
下面操作会释放锁
1.当前线程的同步方法 同步代码块执行结束
2.当前线程在同步代码块 同步方法中遇到break return
3.当前线程在同步代码块 同步方法中出现了未处理的Error 或 Exception 导致异常结束
4.当前线程在同步代码块 同步方法中执行了 线程对象的wait方法 当前线程暂停 并释放锁
下面操作不会释放锁
1.线程执行同步代码块或同步方法时 程序调用Thread.sleep() Thread.yield()方法 暂停当前线程的执行 不会释放锁
2.线程执行同步代码块时 其他线程调用了该线程的suspend()方法 将该线程挂起 该线程不会释放锁
方法不再推荐使用