线程
进程是执行程序的一次执行过程,是系统资源分配的单位,通常在一个进程中可以包含若干个线程,线程是CPU调度和执行的单位。
线程三种创建方式
-
Tread clss:继承Tread类
-
自定义线程类继承Tread类
-
重写run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
-
线程开启不一定立即执行由CPU进行调度执行,Tread也是实现了Runnable接口
- Runnable接口:实现Runnable接口
- 实现Runable接口
- 实现run()方法,编写线程执行体
- 创建线程对象,调用start()方法启动线程
- 推荐使用
- Callable接口:实现Callable接口(了解)
-
实现Callable接口,需要返回值类型
-
重写call方法,需要抛出异常
-
创建目标对象
好处:
- 可以定义返回值
- 可以抛出异常
静态代理模式
- 真实对象和代理对象都要实现同一个接口
- 代理对象要代理真实角色
- 好处:代理对象可以做很多真实对象做不了的事情,真实对象专注做自己的事情
Lamda表达式
函数式接口:任何接口,如果只包含唯一的一个抽象方法,那么它就是一个函数式接口
对于函数式接口可以通过Lamda表达式来创建该接口对象
静态内部类
局部内部类
匿名内部类:没有类的名称 ,必须借助接口或者父类
线程状态
- 线程停止:
- 建议线程正常停止,利用次数
- 建议使用标志位,设置一个标志位
- 不要使用stop或者destroy
- 线程休眠 sleep
每个对象都有一个锁,sleep不会释放锁
-
线程礼让
-
礼让线程,让当前正在执行的线程暂停但不阻塞
-
将线程从运行状态转为就绪状态
-
让cpu重新调度,礼让不一定成功看cpu的心情
Thread.yield(); -
-
线程强制执行
thread.join() -
观测线程状态
Thread.State state=thread.getState();
-
线程优先级
.setPriority(); -
守护线程
-
线程分为用户线程(如main())和守护线程(如gc()线程)
-
虚拟机不用等待守护进程执行完毕,虚拟机必须确保用户进程执行完毕
-
thread.setDaemon(true);默认是false,true为开启 守护进程
-
线程同步
多个线程操作同一个资源(队列+锁)
同步方法和同步块
-
synchronized 方法控制对象的访问,每个对象都有一个锁,每个synchronized方法必须获得调用该方法得锁才能执行否则线程会阻塞,一旦执行就独占该锁直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁继续执行
-
同步块 synchronized (obj){}
-
方法里面需要修改的内容才需要锁,锁太多浪费资源
-
同步方法默认锁的是对象类的本身this,同步块锁任何对象锁变化的量(增删改的)
synchronized (list){ list.add(Thread.currentThread().getName()) }
死锁
产生死锁的必要条件:
- 互斥条件
- 请求和保持条件
- 不可剥夺条件
- 循环等待条件
lock锁
显式定义同步锁对象来实现
ReentrantLock(可重如锁)类实现Lock
jvm将花费较少时间来调度线程,性能更好
private final ReentrantLock lock=new ReentrantLock();
线程协作
生产者和消费者模式
- 生产者---缓存区---消费者
线程池
ExecutorService和Executors
ExecutorService Service=Executors.newFixedThreadPool(10);
Service.execute(new MyThreaad());
Service.shutdown();