- 程序: 静态的、是由有序的指令组成的
- 进程: 动态的、是程序运行后的产物,一个程序至少会产生一个进程。和CPU有关系,是CPU做任务调度和资源分配的基本单位
- 线程: 是比进程更小一个执行单元、是轻量级的、可以充分的利用CPU, 一个进程可以开启多个线程,是 CPU是执行任务的最小单位
-
继承Thread类: Thread类表示一个线程类
-
实现Runnable接口:
-
线程池
class MyThread extends Thread { public void run() { ... 具体任务 } }启动线程
new MyThread().start();实现Runnable接口
new Thread( ()-> { System.out.println("hello thread"); })线程的执行状态
线程的使用场景新建 --> 可执行 --> 执行 —> 死亡
执行 -----> 可执行 (时间片结束)
执行 ----> 阻塞 (1. IO阻塞、 2 sleep, 3 join)
阻塞 —> 可执行 (1. IO阻塞消失, 2 sleep 完成 3 join的线程执行完成)
执行 --> 等待 (wait)
等待 —> 可执行 (notify)
同步锁 synchronized火车站售票
同步代码块将临界资源的访问由并行改为串行、效率降低了,作用是解决多线程并发访问带来的问题
synchronized(obj) { }
obj必须是一个临界资源(多个线程共享的资源)
在方法上使用 synchronized如果synchronized写在方法上、则代表锁的是当前类的对象this
线程的通信- 生产者:
- 消费者:
要求 2个线程负责 生产苹果、 5个线程负责消费苹果
当苹果的数量小于5的时候,停止消费,通知生产者生产苹果,当苹果的数量大于等于100的时候
停止生产、通知消费者消费
- 苹果类
public class Apple { private int num; public int getNum() { return num; } public void setNum(int num) { this.num = num; } }
- 生产者
public class Productor implements Runnable { private Apple apple; private String name; public Productor(Apple apple, String name) { this.apple = apple; this.name = name; } @Override public void run() { // 负责生产苹果, 50毫秒摘一个苹果 while (true) { try { TimeUnit.MILLISECONDS.sleep(500); synchronized ("P") { // 给苹果的数量 + 1 int num = apple.getNum(); // 如果 数量 大于等于 50, 则 停止生产 if (num >= 50) { synchronized ("C") { // 先唤醒消费者 "C".notifyAll(); } // 自己等待 "P".wait(); } num = apple.getNum(); num++; // 修改苹果数量,模拟摘苹果 apple.setNum(num); TimeUnit.MILLISECONDS.sleep(1); System.out.println(name + "摘了一个苹果,原来苹果数量为 " + (num - 1) + "当前苹果数量为" + apple.getNum()); } } catch (InterruptedException e) { e.printStackTrace(); } } } }
- 消费者
public class Consumer implements Runnable { private Apple apple; private String name; public Consumer(Apple apple, String name) { this.apple = apple; this.name = name; } @Override public void run() { while (true) { try { // 模拟吃苹果的时间 TimeUnit.MILLISECONDS.sleep(1800); synchronized ("C") { // 获取 篮子中目前的苹果数 int num = apple.getNum(); // 判断篮子中苹果数量是否小于 5, 如果是,则 停止消费 if (num < 5) { // 停止消费, wait和 nofity 方法必须是 同步锁 锁的对象才能调用 synchronized ("P") { // 唤醒所有生产者 "P".notifyAll(); } //this.wait(); "C".wait(); } // 再次获取篮子中的苹果数量 num = apple.getNum(); // 吃掉苹果 num--; apple.setNum(num); System.err.println(name + "吃了一个苹果、原苹果数" + (num + 1) + ",还剩" + apple.getNum()); } } catch (InterruptedException e) { e.printStackTrace(); } } } }
- 测试类
public class AppleTest { public static void main(String[] args) { // 创建2个生产者 Apple apple = new Apple(); new Thread(new Productor(apple, "张三")).start(); new Thread(new Productor(apple, "李四")).start(); new Thread(new Consumer(apple,"A")).start(); new Thread(new Consumer(apple,"B")).start(); new Thread(new Consumer(apple,"C")).start(); new Thread(new Consumer(apple,"D")).start(); new Thread(new Consumer(apple,"E")).start(); } }``` ).start(); new Thread(new Consumer(apple,"B")).start(); new Thread(new Consumer(apple,"C")).start(); new Thread(new Consumer(apple,"D")).start(); new Thread(new Consumer(apple,"E")).start(); } }