程序:程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
进程:进程则是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位
通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程是 CPU调度和执行的单位。
1、线程就是独立的执行路径
2、在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;
3、main()称之为主线程,为系统的入口,用于执行整个程序;
4、在一个进程中,如果开辟了多个线程,线程的运行由调度器(CPU)安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的干预的。
5、对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;
创建线程方式一: 1、自定义线程类继承Thread类
2、重写run()方法,编写线程执行体
3、创建线程对象,调用start()方法启动线程
总结:注意,线程开启不一定立即执行,由CPU调度执行
创建线程方式二: 1、自定义线程类实现Runnable接口
2、重写run()方法,编写线程执行体
3、创建线程对象,调用start()方法启动线程(需要丢入runnable接口实现类,调用start方法)
多个线程操作同一资源时会产生并发问题,引起数据紊乱。
创建线程方式三:1、实现Callable接口,需要返回值类型
2、重写call方法,需要抛出异常
3、创建目标对象
4、创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1) ;
5、提交执行: Future<Boolean> result1 = ser.submit(t1);
6、获取结果: boolean r1 = result1.get()
7、关闭服务: ser.shutdownNow();
静态代理模式总结:
真实对象和代理对象都要实现同一个接口
代理对象要代理真实角色,通过有参构造传入
好处:代理对象可以做很多真实对象做不了的事情
真实对象专注做自己的事情
Lambda表达式:
任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。
(方法参数)->{主体};
简化1. 去掉参数类型
2. 简化括号
3. 去掉花括号
总结:lambda表达式只能有一行代码的情况下才能简化成为一行,如果有多行,那么就用代码块包裹。
前提是接口为函数式接口
多个参数也可以去掉参数类型,要去掉就都去掉 ,必须加上括号。
线程状态:
停止线程:不推荐使用JDK提供的stop()、destroy()方法。建议使用一个标志位进行终止变量,当flag=false,则终止线程。
线程休眠:sleep指定当前线程阻塞的毫秒数;每一个对象都有一个锁,sleep不会释放锁;
模拟网络延时:放大问题的发生性。
线程礼让:让cpu重新调度,礼让不一定成功!看CPU心情(Thread.yield())
join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞,可以想象成插队
观测线程状态:thread(线程对象).getState();
java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
线程的优先级用数字表示,范围 从1~10 线程对象.setPriority() 设置线程优先级 不设置默认优先级为5
优先级的设定建议在start()调度前,优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,这都得看cpu
守护线程: 线程分为用户线程和守护线程
虚拟机必须确保用户线程执行完毕(main())
虚拟机不用等待守护线程执行完毕(gc())
thread.setDaemon(true或false) 默认是false表示用户线程,正常的线程都是用户线程
并发:同一个对象被多个线程同时操作
线程同步:形成条件:队列+锁 (synchronized)
synchronized 默认锁的是this 同步方法和同步块
public synchronized 返回值类型 方法名() {
}
synchronized(对象){ //锁的对象就是变化的量,需要增删改的对象
可能发生线程安全问题的代码
}
JUC安全类型的集合: CopyOnWriteArrayList
死锁:两个或多个线程各自占有一些资源,都在等待对方释放资源,都停止执行的情况,某一个同步块同时拥有"两个以上对象的锁"时,就可能发生"死锁"的问题。(简单来说就是多个线程互相抱着对方需要的资源,然后形成僵持)
产生死锁的四个必要条件:
1.互斥条件:一个资源每次只能被一个进程使用。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
Lock锁:和synchronized差不多的东西,Lock是显式锁(手动开启和关闭锁,别忘关闭锁) synchronized是隐式锁,出来作用域自动释放 ReentrantLock(可重入锁)
线程通信:wait() 表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁
notify() 唤醒一个处于等待状态的线程
生产者消费者模型 --> 利用缓冲区解决:管程法 信号灯法
线程池:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。
创建服务,创建线程池,参数为线程池大小
ExecutorService ser = Executors.newFixedThreadPool(10) ;
执行
ser.execute(接口的实现类对象);
关闭连接
ser.shutdown();