线程的创建方式
1、实现Runnable
Runnable规定的方法是run(),无返回值,无法抛出异常 实现Callable
2、Callable规定的方法是call(),任务执行后有返回值,可以抛出异常
3、继承Thread类创建多线程
继承java.lang.Thread类,重写Thread类的run()方法,在run()方法中实现运行在线程上的代码,调用start()方法开启线程。 Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过 Thread 类的 start()实例方法。start()方法是一个 native 方法,它将启动一个新线程,并执行 run()方法 通过线程池创建线程. 线程和数据库连接这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是使用线程池。
wait和Sleep的区别
sleep wait
不释放锁对象 释放锁对象,需要notify进行唤醒
在任何地方(可以定时) 同步方法,同步代码块
必须捕获异常 不要捕获异常
线程和进程
线程 进程
系统运行的基本单位,程序执行的最小单位 系统资源分配和调度的基本单位
线程状态
新建 就绪 运行 阻塞 销毁
synchronized和Lock的区别
synchronized lock
主动释放锁 final里面进行强制释放
不可中断,非公平锁 可以判断,公平锁
少量同步 大量同步
独占锁 公平锁和非公平锁
多线程之间如何通信
1、使用volalite修饰变量,进行变量共享
2、使用wait
线程池参数
1、线程池大小
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
2、最大线程数量
3、空闲线程存活时间
4、工作队列
5、线程工厂
线程的拒绝策略
线程自旋锁
自旋锁是一种多线程同步的变量;
使用自旋锁的线程会反复检查锁变量是否可用,如果不可用会一直循环反复检查;
自旋锁不会让出CPU,是一种忙等待状态; 自旋锁是一种死循环等待锁被释放;
join和yield
join的原理就是wait方法
t.join()表示等待t线程执行完毕后再执行
join线程有严格的先后顺序,调用它的线程需要执行完以后其他线程才会跟着执行。
yield 是指线程让步,使其线程从运行状态变为启动状态
当一个线程调用yield时会把这个线程的锁 ,抛出去,使其和它一样优先级的线程进行获取锁,当然这个线程本身也会参与锁的竞争,并有可能获取锁对象,重新执行
yield是暂停当前正在执行的线程对象,把时间让给其他线程。
使用场合:join线程有严格的先后顺序,yield当前线程占用cpu使用率很高时,把时间让出来。(死循环时)
线程的优先级
线程的优先级就是设置哪个线程优先执行,但也不是绝对的,只是让优先级高的线程优先运行的几率高一些。
线程默认是NORM_PRIORITY = 5; 设置优先级使用的是setPriority()函数。
Tread里面的方法大多数是final进行修饰的,防止继承的时候进行修改
线程间的相互通信
线程间是通过相互作用,共同完成一个任务当一个线程调用wait方法后便进入等待状态,需要另一线程调用notify()方法对它进行唤醒。
notifyAll可以唤醒所有线程,都必须在synchronized方法或synchronized块里使用
wait ,notify , notifyAll都必须在synchronized修饰的方法或synchronized块中使用,都属于Object的方法,可以被所有类继承,都是final修饰的方法,不能通过子类覆写去改变他们的行为。
处理线程安全的措施
1、放在栈里面的数据都是线程安全的
2、同步关键字或者同步代码块
3、final修饰的变量都是线程安全的
4、TreadLoad放置的变量
5、使用线程安全的集合和类等
stop
stop()方法作为一种粗暴的线程终止行为,在线程终止之前没有对其做任何的清除操作,因此具有固有的不安全性。