Java学习_20220627
多线程详解
1. 线程同步机制
多个线程访问同一个对象,并且某些线程还想修改这个对象,使用线程同步。是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用。
形成条件:队列+锁 (解决线程安全问题)
(1)锁机制:synchronized,当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用后释放锁即可。
存在以下问题:
一个线程持有锁会导致其他所有需要此锁的线程挂起,引起性能问题,一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题。
两种用法:
synchronized方法和synchronized块
同步方法:public synchronized void method(int args){}
同步方法,默认锁的是this,,,可以锁run方法
同步块:synchronized(obj){}:obj同步监视器,可以是任何对象,使用共享资源(需要修改的对象)作为同步监视器。
锁的对象是变化的量,需要增删改的对象。
@Override
public void run() {
synchronized (account){ //是对account进行操作
//判断账户中的余额是否足够
if(account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"钱不够了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内余额
account.money = account.money-drawingMoney;
nowMoney = nowMoney+drawingMoney;
System.out.println(account.name+"余额为:"+account.money);
System.out.println(this.getName()+"手里的钱"+nowMoney);
}
}
}
(2)JUC中关于安全类型的集合List
CopyOnWriteArrayList
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
for (int i = 0; i < 1000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
2.死锁
多个线程互相之间抱着对方需要的资源,形成僵持。
某一个同步块同时拥有“两个以上对象的锁”时,就可能会发生哪个“死锁”的问题。相互等待对方的释放资源,都停止执行
产生死锁的四个必要条件:
(1)互斥条件:一个资源只能被一个进程使用;
(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;
(3)不剥夺条件:进程已获得的资源,在为使用完之前,不能强行剥夺;
(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
3. Lock锁
ReentrantLock 可重入锁,可以显示加锁、释放锁。
定义lock锁,只能锁代码块
class A{
private final ReentrantLock lock = new ReentrantLock();
public void m(){
lock.lock();//加锁
try{
//不安全的代码
}finally{
lock.unlock();//解锁
//如果同步代码有异常,要将unlock()写入finally语句块
}
}
}
4. 线程协作
this.wait(),等待,可释放锁
this.notify(),唤醒线程
5. 线程池
提前创建多个线程,放入线程池中,使用时直接获取,使用完放回池中,可以比米娜频繁创建销毁、实现重复利用。提高相应速度,降低资源消耗,便于线程管理。
API:
ExecutorService:线程池接口
void execute(Runnable command):没有返回值,用来执行Runnable
<T> Future <T>submit(Callable<T>task):有返回值,用来执行Callable
void shutdown():关闭连接池
public class TestPool {
public static void main(String[] args) {
//创建服务,创建线程池
//newFixedThreadPool(10),参数为线程池大小
ExecutorService service = Executors.newFixedThreadPool(10);
//执行
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//关闭连接池
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
Executors:线程池的工厂类,创建返回不同类型的线程池。
浙公网安备 33010602011771号