多线程初始
线程简介
多任务
进程
-
资源分配的最小单位
-
运行起来的程序
-
可以拥有多个线程
线程
-
资源调度的最小单位
-
独立执行的路径
-
线程的运行由调度器调度,前后顺序是不能人为干预的
-
对于同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制
-
线程会带来额外的开销
-
每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
注意:很多多线程都是模拟出来的额,真正的多线程是指有多个CPU,即多核。如果是模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快。所以就有同时执行的错觉。
线程实现(重点)
Thread类
-
自定义线程类继承Thread类
-
重写run()方法,编写线 程执行体
-
创建线程对象,调用strat()方法
Runnable接口(建议)
-
定义实现类,实现Runnable接口
-
重写run()方法,编写线程执行体
-
创建线程对象,构造函数中传入实现类对象,线程对象执行start()方法
静态代理
-
真实对象和代理对象都实现同一个接口
-
代理对象需要代理真实对象,即真实对象传入代理对象
代理对象可以做很多真实对象做不了的事情
真实对象专注做自己该做的事情
Lambda表达式
函数式接口
-
普通实现类
-
静态内部类(需要的功能只需要一次)
-
局部内部类(需要的功能只需要一次)
-
匿名内部类(需要的功能只需要一次,需要的时候实现接口中的方法)
-
lambda表达式简化
函数式接口
函数式编程
避免匿名内部类定义过多
Callable接口(了解)
-
实现Callable接口,该接口需要返回值类型,与call方法返回值相同
-
重写call()方法,该方法有返回值
-
创建目标对象
-
创建执行服务
-
提交执行
-
获取结果
-
关闭服务
call()方法有返回值
可以抛出异常
线程不安全问题
线程状态
五大状态
创建,就绪,执行,阻塞,死亡
-
Thread方法
-
sleep()
-
join()
-
isAlive()
-
等等
-
线程休眠 sleep
-
Thread.sleep()
线程礼让 yield
-
Thread.yield()
-
将该线程有运行状态转为就绪状态,让cpu重新调度,礼让不一定成功
插队线程join
-
threadObj.join();
线程状态
-
Thread.State
-
threadObj.getState()
-
NEW
-
RUNNABLE
-
BLOCKED
-
WAITING
-
TIME_WAI TING
-
TERMINATED
-
线程的优先级
-
threadObj.setProprity()
-
threadObj.getProprity()
-
范围1~10,值越大,优先级越高
守护线程 daemon
-
threadObj.setDaemon()
-
线程分为用户线程和守护线程
-
main线程
-
gc线程
-
-
正常的线程都是用户线程
-
虚拟机不必等待守护线程执行完毕
线程同步(重点)
-
多个线程操作同一个资源
-
线程同步本质上是一种等待机制,多个需要同时访问此对象的线程进入对象的等待池形成队列
-
synchronized
队列+锁
三大不安全案例
-
不安全买票
-
不安全银行取票
-
线程不安全的集合
同步方法及同步方法块
-
方法上synchronized修饰符
-
存在问题:锁太多,浪费资源
-
-
同步块
-
synchronized(Obj) {}
-
-
锁的对象就是变化的量。需要增删改的对象
-
同步方法,this,指向这个类本身
-
同步方法,谁变化锁谁。产生不安全的代码块,写在锁中
-
JUC安全类型的集合
-
CopyOnWriteArrayList线程安全
-
ArrayList线程不安全
死锁
-
多个线程互相抱着对方需要的资源,并僵持住
-
先抱着锁着自己的资源不放,并在锁住自己资源的内,还想锁住其他别人拥有的资源
-
-
产生死锁的四个必要条件
-
互斥条件
-
请求与保持条件
-
不剥夺条件
-
循环等待
-
LOCK接口
-
使用ReentrantLock类实现Lock
-
显式加锁和释放锁
-
-
reentrantLockObj.lock();
-
reentrantLockObj.unlock();
Synchronized与Lock对比
-
Lock显式,Synchronized隐式
-
Lock只有代码块,Synchronized有方法锁和代码块锁
-
Lock性能更好
优先使用顺序
Lock>同步代码块>同步方法
线程通信问题
生产者消费者模式
-
在生产者和消费者问题中,仅有Synchronized是不够的
-
synchronized可以阻止并发更新同一个共享资源,实现了同步
-
synchronized不能用来实现 不同线程之间的通信
-
线程通信方法
wait()
wait(long time)
notify()
notifyAll()
解决方式一:管程法->缓冲区
public class TestPC { public static void main(String[] args) { Container container = new Container(); new Producer(container).start(); new Consumer(container).start(); } } //生产者 class Producer extends Thread { Container container; public Producer(Container container) { this.container = container; } @Override public void run() { for (int i = 0; i < 100; i++) { container.push(new Product(i)); System.out.println("生产了第"+ i + "个产品"); } } } //消费者 class Consumer extends Thread { Container container; public Consumer(Container container) { this.container = container; } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("消费了第"+ container.get().id + "个产品" ); } } } //产品 class Product { int id; public Product(int id) { this.id = id; } } //缓冲区 class Container { //存放产品的容器大小 Product[] products = new Product[10]; int count = 0; //生产者放入产品 public synchronized void push(Product product) { //如果容器满了,就需要等待消费者消费 if(count == products.length){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没有满,就需要想容器中丢入产品 products[count] = product; count++; //通知消费者进行消费 this.notifyAll(); } //消费者消费产品 public synchronized Product get() { //没产品了,等待生产者生产 if(count == 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果有产品,则可以消费 count--; Product product = products[count]; //消费完,通知生产者生产 this.notifyAll(); return product; } }
解决方式二:信号灯法
public class Test { public static void main(String[] args) { Food food = new Food(); new Machine(food).start(); new Diner(food).start(); } } //生产者 class Machine extends Thread{ Food food; public Machine(Food food) { this.food = food; } @Override public void run() { for (int i = 0; i < 20; i++) { this.food.make("鱼香肉丝"); } } } //消费者 class Diner extends Thread { Food food; public Diner(Food food) { this.food = food; } @Override public void run() { for (int i = 0; i < 20; i++) { this.food.eat(); } } } //食物 class Food { //机器制作食物时,(食客等待 true) //食客吃饭时,(机器等待 false) String foodName; boolean flag = true; //制作食物 public synchronized void make(String foodName) { //假定flag为false时,机器等待 if(!flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("机器制造了"+ foodName); //通知食客吃饭 this.notifyAll(); this.foodName = foodName; //更新标志 this.flag = !flag; } //食客吃饭 public synchronized void eat() { //假定flag为true时,食客等待 if (flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("食客吃饭了" + foodName); //通知机器制作食物 this.notifyAll(); //更新标志 this.flag = !flag; } }
高级主题
线程池
-
降低资源消耗
-
提高响应速度
-
便于线程管理
Executos工具类与ExecutorService
-
ThreadPoolExecutor类
-
Executors.newFixedThreadPool()
-
-
serviceObj.execute(threadObj)->执行Runnable
-
-

浙公网安备 33010602011771号