多线程(Thread)
程序:指令和数据的有序集合,其本身没有任何运行的含义,是静态概念。
进程:程序的一次执行过程,它是一个动态概念。是系统分配资源的单位。
线程:一个进程中至少有一个线程。线程是CPU调度和执行的单位。
注意:
很多多线程是模拟出来的,真正的多线程是指有多个CPU,即多核,如服务器。如果是模拟出来的多线程,即在一个CPU的情况下,在同一个时间点,CPU只能执行一个线程,因为切换的很快,所以就有同时执行的错觉。
线程创建
- 方法一:
继承Thread类,重写run()方法,实例化线程对象调用start()方法开启线程
启动线程:子对象.start()
- 方法二:
定义一个类实现Runnable接口,实现run方法编写线程执行体,创建线程对象,调用start()方法启动。
启动线程:new Thread(Runnable接口实现类对象).start()
推荐使用Runnable接口避免单继承的局限性,方便同一个对象被多个线程使用。
- 方法三 :(了解即可)
1.实现Callable接口,需要返回值类型
2.重写call方法需要抛出异常
3.创建目标对象
4.创建执行任务:ExecutorService ser =Executors.newFixedThreadPool(1);
5.提交执行:Futureresult1=ser.submit(t1);
6.获取结果:boolean b1=reault1.get()
7.关闭服务:ser.shutdownNow();
静态代理
1.真实对象和代理对象要实现同一个接口
2.代理对象代理真实对象
好处:代理对象可以做很多真实对象做不了的事情
λ表达式
函数式接口(Functional Interface)定义:
任何接口,若只包含唯一一个抽象方法,那么它就是一个函数式接口,对于函数式接口我们可以通过λ表达式来创建该接口对象。
匿名内部类:
接口名:Love
接口实现类名:Like
Love love=new Like();
love= new Love(int a){
public void haha(){
方法体;
}
}
λ表达式:
love=(a)->{方法体;};
线程停止
推荐让线程自己停下来,建议使用一个标志位进行终止变量当flage=false,则终止线程运行。
线程休眠
1.sleep(ms)指定当前线程阻塞的毫秒数
2.sleep存在异常InterruptedException;
3.sleep时间达到后线程进入就绪状态
4.sleep可以模拟网络延时,倒计时等
5.每一个对象都有一个锁,sleep不会释放锁
线程礼让
将线程从运行状态转为就绪状态
cup在就绪队列里随机挑选线程进入运行,所以礼让不一定成功
调用yield()方法
join合并线程
待此线程执行完成后,再执行其他线程,其他线程阻塞,可以想象成插队
线程状态观测
Thread.State线程状态
线程优先级
使用以下方法改变或获取优先级:
getPriority(),setPriority(int xx)
线程同步
处理多线程问题时,多个线程访问同一个对象,并且某些线程还想修改这个对象,这时候我们就需要线程同步。
线程同步实际上是一种等待机制,多个需要同时访问此对象的线程进入对象等待池形成队列,等待前面线程使用完毕下一个线程再使用。
同步方法
Synchronized关键字
Synchronized方法控制对对象的访问,每个对象对应一把锁,每个Synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程就会阻塞。方法一旦执行就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得该锁,继续执行。
public Synchronized void method(int X){
}