7.25内容

线程锁对象

锁对象  lock
Lock lock = new ReentrantLock(true);
创建锁对象  默认非公平锁 加true才是公平锁

 wait  

notify   

notifyAll  

wait  sleep区别

wait是Object中定义的方法,可以有锁对象调用,让执行到该代码的线程进入到等待状态

sleep是Thread类中定义的静态方法,可以让执行到该代码的线程进入到等待状态
区别:sleep需要传入一个毫秒数,到达时间后会自动唤醒 wait不能自动唤醒,必须调用notity/notityAll方法唤醒
sleep方法保持锁状态进入等待状态 wait方法会解除锁状态,其他线程可以进入运行

ReentrantReadWriteLock类

  1. 读锁

    • 可以被多个线程同时获取,即支持共享锁。
    • 当没有写锁的时候,读锁可以被任意数量的读线程获取。
    • 当有写锁的时候,读锁会等待写锁释放后再获取。
    • 读锁是不可重入的,即同一个线程无法获取多次读锁。
  2. 写锁

    • 只能被一个线程获取,即独占锁。
    • 写锁是可重入的,即同一个线程可以多次获取写锁。
    • 当有写锁的时候,其他线程的读锁和写锁请求都会被阻塞。
    • 当有读锁的时候,写锁的请求会被阻塞,直到所有读锁都被释放。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class EasyThreadC {
    public static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    public static ReentrantLock rl = new ReentrantLock();
    public static void method(){
        System.out.println(Thread.currentThread().getName()+"进入方法");
       Lock lock= rwl.readLock();
       lock.lock();
        System.out.println(Thread.currentThread().getName()+"加锁成功----读锁");
        try{
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        lock.unlock();
        System.out.println(Thread.currentThread().getName()+"方法结束");
    }
    public static void methodWrite(){
        System.out.println(Thread.currentThread().getName()+"进入方法");
        Lock lock= rwl.writeLock();
        lock.lock();
        System.out.println(Thread.currentThread().getName()+"加锁成功----写锁");
        try{
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        lock.unlock();
        System.out.println(Thread.currentThread().getName()+"方法结束");
    }

    public static void main(String[] args) {
        Runnable run = EasyThreadC::method;
        Runnable runWrite = EasyThreadC::methodWrite;
        Thread a = new Thread(run);
        a.start();
        Thread b = new Thread(run);
        b.start();
        Thread c = new Thread(run);
        c.start();
        Thread d = new Thread(run);
        d.start();
        Thread e = new Thread(runWrite);
        e.start();
        Thread f = new Thread(runWrite);
        f.start();
        Thread g = new Thread(runWrite);
        g.start();
        Thread h = new Thread(runWrite);
        h.start();
        System.out.println("main------end");
    }
}

   线程池

 池==重用
完成线程创建和管理,销毁线程工作
线程任务  Runable Callable
Runnable run=EasyExecuters::method;
tpe.execute(run);
Callable<String> call=EasyExecuters::methodCall;
Future<String> f=tpe.submit(call);
//tpe.submit(run);
System.out.println(f.get());//会等待线程执行完毕

//关闭线程对象
tpe.shutdown();
public class EasyExecuters {
    //线程池  池==重用
    //完成线程创建和管理,销毁线程工作
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        BlockingQueue qu = new ArrayBlockingQueue(12);
        ThreadPoolExecutor tpe = new ThreadPoolExecutor(5,10,10,
                TimeUnit.SECONDS,qu,Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
        //线程任务  Runable Callable
        Runnable run=EasyExecuters::method;
        tpe.execute(run);
        Callable<String> call=EasyExecuters::methodCall;
        Future<String> f=tpe.submit(call);
        //tpe.submit(run);
        System.out.println(f.get());//会等待线程执行完毕

        //关闭线程对象
        tpe.shutdown();
    }
    public static void method(){
        System.out.println(Thread.currentThread().getName()+"执行代码");
    }
    public static String methodCall() throws InterruptedException{
        System.out.println(Thread.currentThread().getName()+"执行代码Call");
        Thread.sleep(2000);
        return "callResult";
    }
}

线程池的七个参数

在Java中,线程池通常使用ThreadPoolExecutor类来实现,它有7个主要的参数:

  1. corePoolSize(核心线程数):

    • 线程池中维持的最小线程数。
    • 即使这些线程处于空闲状态,也不会被终止。
    • 在没有任务执行时,核心线程也不会被回收。
  2. maximumPoolSize(最大线程数):

    • 线程池中允许的最大线程数。
    • 当队列满了且已有的线程数小于最大线程数时,会创建新的线程来处理任务。
  3. keepAliveTime(线程存活时间):

    • 当线程池中的线程数超过corePoolSize时,多余的空闲线程在等待新任务到来时会终止。
    • keepAliveTime指定了这些空闲线程的存活时间。
  4. unit(时间单位):

    • keepAliveTime参数配合使用,指定keepAliveTime的时间单位。
    • 通常使用TimeUnit枚举类的实例,如TimeUnit.SECONDSTimeUnit.MINUTES等。
  5. workQueue(任务队列):

    • 用于保存等待执行的任务的阻塞队列。
    • 当所有corePoolSize大小的线程都在忙碌时,新任务会被添加到这个队列中。
  6. threadFactory(线程工厂):

    • 用于创建新线程的工厂。
    • 可以通过自定义线程工厂来设置线程的名称、优先级等属性。
  7. handler(拒绝处理策略):

    • 当任务无法被添加到工作队列中时,线程池会采取的饱和策略。
    • 常见的策略有:AbortPolicy(抛出RejectedExecutionException异常)、CallerRunsPolicy(在调用者线程中执行任务)、DiscardOldestPolicy(丢弃最早的未处理任务)、DiscardPolicy(静默地丢弃任务)。

线程池的四种回绝策略 

AbortPolicy  放弃该任务并会抛出一个异常
CallerrunsPolicy  调用者执行,让传递任务的线程执行此任务
DiscardOldestPolicy  放弃队列中最长的任务,不会抛出异常
DiscardPolicy    直接放弃新的任务,不会抛出异常

四种内置线程池(缓存线程池,定时运行线程池,边界线程池,单例线程池)

Java中提供了4种内置的线程池:

1. 缓存线程池(CachedThreadPool):
   - 使用`Executors.newCachedThreadPool()`创建。
   - 线程池初始没有任何线程,当有任务来时会创建新线程执行,闲置60秒后会被回收。
   - 适用于执行大量短期异步任务的场景。

2. 定时运行线程池(ScheduledThreadPool):
   - 使用`Executors.newScheduledThreadPool()`创建。
   - 线程池包含`corePoolSize`指定数量的线程,用于执行定时或周期性任务。
   - 适用于需要延迟执行或定期执行的任务。

3. 边界线程池(FixedThreadPool):
   - 使用`Executors.newFixedThreadPool()`创建。
   - 线程池大小固定,线程数等于`corePoolSize`和`maximumPoolSize`。
   - 适用于负载比较平稳的场景,可控制并发的线程数。

4. 单线程池(SingleThreadExecutor):
   - 使用`Executors.newSingleThreadExecutor()`创建。
   - 线程池中只有一个线程,任务会被顺序执行。
   - 适用于需要保证任务顺序执行的场景,例如日志记录。

线程池的工作原理  

任务放置在工作队列中
池中是否有空闲的线程,如果有就让该线程执行任务
如果没有空闲的线程,判断池中的线程数量有没有达到核心线程数
如果没有达到创捷新的线程执行任务,如果已经达到,优先在队列中存储
直到队列填满;
工作队列填满后在添加新的任务,判断是否达到最大线程数,如果没有创建新的线程执行任务
知道填满最大线程数
已经填满的最大线程数,队列也已经填满,没有空闲的线程,就执行回绝策略
线程池中的线程达到(超过)核心线程数,超出的数量会根据存活时间,进行销毁,直到数量达到核心线程数
如果线程的数量少于核心线程数,不会消亡

死锁(Deadlock)是指两个或多个线程在执行过程中,因争夺资源而造成的一种僵持状态。当线程1持有资源A并请求资源B,而线程2正持有资源B并请求资源A,这样两个线程都在等待对方释放资源,就会形成死锁。

什么是死锁

形成死锁需要满足以下4个条件:

1. **互斥条件**:资源只能被一个线程使用,不能被其他线程共享。
2. **请求和保持条件**:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
3. **不可剥夺条件**:线程已获得的资源,在未使用完之前,不能被其他线程强行剥夺。
4. **循环等待条件**:存在一个线程-资源的循环等待链。

这4个条件缺一不可,只要有任何一个条件不成立,死锁就不会发生。

常见的避免死锁的方法有:

1. 破坏互斥条件:改用共享资源代替独占资源。
2. 破坏请求和保持条件:一次性申请所有需要的资源。
3. 破坏不可剥夺条件:占用资源的线程结束时主动释放资源。
4. 破坏循环等待条件:对资源加上全局排序,按序申请资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值