一个main方法就是一个jvm进程,一个进程中包含多个线程
多线程方式有三种
多进程单线程
单进程多线程
多进程多线程
线程的创建
继承Thread类,实现run()方法,
实现Runable接口,实现run()方法,
通过start()方法来启动线程,在类中直接调用start()方法是调用不起来线程的。
可以调用interrupt()方法来中断线程
线程的状态
new 新创建
runable 运行中
blocked 阻塞
waiting 等待
time waiting 计时等待
terminated 终止
线程执行顺序
线程的执行时无序的,可以设置线程的优先级,来增加线程的调用几率,但是不能通过设置优先级来改变线程的调用顺序。
可以通过join()方法,来等待一个线程执行完成,在继续执行下一个线程
valatile关键字,解决线程可见性的问题,当一个线程修改了共享变量的值后,保证其他线程获取共享变量的值是修改后的值。
守护线程
守护线程不能打开支援,因为守护线程不能关闭资源,会导致数据丢失
守护线程,当所有非守护线程执行完成后,守护线程自动关闭
通过设置deamon的属性为true,来设置守护线程
synchronized方法
可以修饰方法,代码块,修饰方法的时候,方法内的所有代码块都是线程安全的,修饰代码块的时候,那么所修饰的代码块是线程安全的,没有修饰的地方不是线程安全的
使用synchronize(lock)修饰代码块时 ,多个线程同时操作共享代码块时,这个lock需要使用同一个。
常见得原子性的类,int,Integer,String,StringBuffer,HashTable,Math,LocalDate等
不安全的,long,double,hashMap等
死锁
java线程中可以载入多个锁
多线程中各自持有不同的锁,并互相试图获取对方持有的锁,就会导致死锁。
死锁没有很好的解决方案,只能强制杀死进程,所以在开发过程中要尽量避免死锁
避免死锁:多线程加锁的顺序要一致。
wait/notify
wait/notify用于多线程的协调调用
在synchronized内部可以调用wait()进行线程等待,调用wait()方法时,会释放锁
必须在已获得的锁的对象上调用wait()方法
在synchronized内部可以调用notify()/notifyAll()的方法可以唤起线程,
必须在已获得的锁的对象上调用notify()/notifyAll()方法
顺序:线程A获取锁执行-----不满足条件进行wait()等待释放锁------线程B获取锁执行-调用notifyAll()方法唤起等待的A线程的锁,释放锁-----线程A获取锁----进行执行完成
ReentrantLock
ReentrantLock可以替代synchronized
ReentrantLock获取锁更加安全
尽量使用try。。。finally保证正确的获取锁和释放锁
ReadWriteLock
使用readwritelock可以提升读的效率
readwritelock只允许一个线程写入,运行多个线程读取,适合读多写少的场景
Condition
Condition可以替代wait/notify
Condition对象必须冲ReentrantLock对象获取
ReetrantLock+Condition可以替代synchronized + wait/notify