多线程
陌生英文单词
Priority //优先级
创建线程的步骤
- 继承Thread类,重写run方法,创建Thread子类对象,调用start方(start的作用是开启线程,并且调用run方法,如果直接调run方法的话就没有开启线程,就是普通的对象调方法)
- 实现Runable接口重写run方法创建Runable子类对象,传入创建好的Runable子类对象构造Thread对象,然后调用Thread对象的start方法
Thread类的api
静态方法
currentThread()//返回当前执行的线程
sleep(long milltimes)//阻塞指定的毫秒值
yeild()//让出cpu执行权 让该线程进入就绪状态
属性(内部封装了)
String name //线程的名字
int priority//线程的优先级(优先级高从概率上来说是先执行的概率高但是不一定先执行)
常量
MIN_PRIORITY = 1//最小优先级
NORM_PRIORITY = 5 //默认优先级
MAX_PRORITY = 10//最大的优先级
成员方法:
join() //在a线程中b线程调用join方法a线程就会进入阻塞状态直到B线程执行完
isAlive()//判断当前线程是否还活着
setDaemon(boolean b);//当参数为true的时候是将该线程转换为守护线程
线程的分类
-
守护线程
守护线程:例如像gc()这样的,等到用户线程结束守护线程才会结束
用户线程:用户线程就是像main方法这样的线程
线程的状态
新建 就绪 运行 阻塞 死亡
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8lePNafz-1655119636742)(img/thread.png)]
线程的安全问题
发生条件:在多个线程中共享同一个变量的时候就会引发线程安全问题,没有保证事务的原子性
解决方法:
1.同步代码块
synchronized(同步监视器){
需要同步的代码
}
同步监视器就是锁(java中只要是对象就可以当锁,不过必须是同一个对象不然就会引发线程安全问题),只有拿到锁的线程才有资格进行操作,其他只能阻塞那些要保持原子性的代码就可以放在代码块里
2.同步方法,就是将synchronized关键字放入方法的声明中,如果是静态方法synchronized默认监视器是当前类的Class对象,如果是成员方法默认监视器就是his
3.Lock对象
java.util.concurrent.locks.Lock类的子类,ReentrantLock ,ReentrantLock(true)//如果给定true这个就是一把公平的锁也就是说它会安按照顺序会分配同步代码的执行
把有线程安全的代码前可以加上lock.lock()//加锁 lock.unlock()//解锁
死锁问题
产生原因:如果多个线程互相占有需要的锁,并且需要得到对方的锁才能释放自己的锁的时候就会发生死锁问题
线程通信
wait()//让当前线程进入阻塞状态,让出同步监视器,
notify()//唤醒一个线程
notifyAll()//唤醒所有的线程
以上三个方法都是从Object类中继承过来的,并且必须写在sychronized块中,同步监视器对象.wait()来调用
JDK5中新建创建线程的几种方式
使用callable的方式
1.实现callable接口
2.重写call方法
3.利用callable子类对象创建FutureTask对象,在利用FutureTask对象构造Thread对象,调用 thread对象的start方法就可以启动线程了
4.如果要获取线程执行完成的返回值的,可以调用FutureTask对象的get()方法
使用线程池的方式
使用线程池的方式
Excutors.newFixedInstance(int bound)//创建固定数量的线程 返回对象是一个ExcutorService的接口,将这个接口转换成子类我们就可以得到对应的ThreadPoolExcutor对象
ThreadPoolExcutor常用方法:
excute(Runnable run)//根据runable对象开启一个线程去执行这个任务
shutdown()//关闭线程池
ThreadPoolExcutor常用属性
corePoolSize 线程池的大小
maximumPoolSize 最大线程数
keepAliveTime 线程没有任务最多保持多长时间后会终止