Java学习笔记10

今日内容:

线程锁对象 wait notify notifyAll 

Lock ReentrantLock true公平锁方法lock   tryLock    unlock  ReentrantReadWriteLock

线程池的定义   Callable    线程池对象执行Runnable 和Callable     Future    get     

线程池的七个参数    线程池的四种回绝策略    四种内置线程池(缓存线程池,定时运行线程池,边界线程池,单例线程池)  线程池的工作原理

锁对象  

wait让执行到该行代码的线程进入等待状态

notify唤醒一条被该锁对象wait 的线程

notifyAll 唤醒所有被该锁对象wait的线程

wait和sleep的区别

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

sleep是Thread类中定义的静态方法,也可以让执行到该行的线程进入到等待状态

区别:

 1.功能上sleep需要传入一个毫秒数,到达时间后会自动唤醒。

    wait不能自动唤醒必须调用notify/notifyAll方法手动唤醒

 2.sleep方法保持锁状态进入等待状态,其他进程不能进入运行。

    wait方法解除锁状态进入等待状态,其他进程可以进入运行。

代码示例:

public class EasyThreadD {

    public static final Object OBJ = new Object();//锁对象尽量不使用字符串



    public static void method(){

        System.out.println(Thread.currentThread().getName() + "进入方法");

        synchronized (OBJ){//锁对象

            OBJ.notify();//唤醒一条被该锁对象wait的线程

            //OBJ.notifyAll();//唤醒全部被该对象wait的线程

            System.out.println(Thread.currentThread().getName() + "进入同步代码块");

            try {

                try {

                    System.out.println(Thread.currentThread().getName() + "进入等待状态");

                    OBJ.wait();//让执行到该行代码的线程进入等待状态(等待值)

                    System.out.println(Thread.currentThread().getName() + "重新运行");

                } catch (InterruptedException e) {

                    throw new RuntimeException(e);

                }

                Thread.sleep(1000);

            } catch (InterruptedException e) {

                throw new RuntimeException(e);

            }

            System.out.println(Thread.currentThread().getName() + "结束同步代码块");

            OBJ.notify();

        }

    }

    

public static void main(String[] args) {

        Runnable run = EasyThreadD::method;

        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();

    }

锁对象 Lock

Lock lock = new ReentrantLock();//创建锁对象,非公平锁

Lock lock = new ReentrantLock(true);//创造公平锁,和非公平锁的区别是true

lock.lock();//加锁

lock.tryLock();//尝试加锁  枷锁成功返回True 失败返回false

lock.unlock();//解锁

ReentrantReadWriteLock

ReentrantReadWriteLock 是 Java 并发包 java.util.concurrent.locks 中的一个类,它实现了 ReadWriteLock 接口。这个锁允许高并发地访问共享资源,同时保证在写操作(独占访问)时数据的完整性和一致性,以及在读操作(共享访问)时提供比独占锁更高的并发级别。

主要特点和用法

读写分离:ReentrantReadWriteLock 分为读锁和写锁。多个读操作可以同时进行(只要没有写操作正在进行),而写操作是独占的,即同一时间只允许一个线程进行写操作。

重入性:与 ReentrantLock 类似,ReentrantReadWriteLock 的读锁和写锁都支持重入。这意呀着,持有锁的线程可以多次获取同一把锁,而不会发生死锁。

公平性:ReentrantReadWriteLock 提供了两种构造器,允许用户指定是否采用公平锁。在公平锁模式下,线程将按照它们请求锁的顺序来获取锁。然而,公平锁会降低性能,因为需要维护一个队列来跟踪等待锁的线程。

锁降级:在持有写锁的情况下,线程可以获取读锁,然后释放写锁,实现从写锁到读锁的降级。但是,不允许锁升级,即持有读锁的线程不能直接获取写锁,因为这样做会破坏读锁和写锁之间的隔离性。

使用案例

import java.util.concurrent.locks.ReadWriteLock;  

import java.util.concurrent.locks.ReentrantReadWriteLock;  

  

public class Cache {  

    private final Map<String, Object> map = new HashMap<>();  

    private final ReadWriteLock lock = new ReentrantReadWriteLock();  

  

    public void put(String key, Object value) {  

        lock.writeLock().lock();  

        try {  

            map.put(key, value);  

        } finally {  

            lock.writeLock().unlock();  

        }  

    }  

  

    public Object get(String key) {  

        lock.readLock().lock();  

        try {  

            return map.get(key);  

        } finally {  

            lock.readLock().unlock();  

        }  

    }  

}

线程池

目的:为了线程重用

完成线程创建,管理和销毁的工作

线程任务  Runnable  Callable

Runnable:最后使用.execute()和.submit()都可以        

Runnable run = EasyExecuters::method;

tpe.execute(run);

Callable:最后只能使用.submit()

Callable<String> call = EasyExecuters::methodCall;

        Future<String> f = tpe.submit(call);

//        tpe.submit(call);

关闭线程池对象

        tpe.shutdown();

线程池示例

BlockingQueue qu = new ArrayBlockingQueue(12);

ThreadPoolExecutor tpe = new ThreadPoolExecutor(5, 10, 10,TimeUnit.SECONDS, qu,Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

说明线程池的七个参数

corePoolSize(核心线程数):线程池中的核心线程数,即使这些线程处于空闲状态,线程池也会保留它们,而不是销毁它们。

maximumPoolSize(最大线程数):线程池中允许的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会尝试创建新线程来执行任务。

keepAliveTime(线程存活时间):当线程数大于核心线程数时,这是多余的空闲线程在终止前等待新任务的最长时间。

unit(时间单位):keepAliveTime参数的时间单位,如TimeUnit.SECONDS。

workQueue(工作队列):用于存放待执行的任务的阻塞队列。这个队列的实现会影响线程池的行为。例如,ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。

threadFactory(线程工厂):用于创建新线程的工厂。通过自定义线程工厂,可以设定线程的优先级、名称、是否为守护线程等。

handler(拒绝策略):当工作队列和线程池都达到饱和状态时,线程池会采取的策略。Java提供了几种预定义的拒绝策略,如AbortPolicy(直接抛出异常)、CallerRunsPolicy(由调用者执行)、DiscardOldestPolicy(丢弃队列中最老的任务)、DiscardPolicy(静默丢弃无法处理的任务)。

线程池的工作原理:

        //   任务放置在工作队列中

        //1>接收到任务后查看池中是否有空闲的线程,如果有让该线程执行任务

        //2>如果没有空闲的线程,判断池中的线程数量有没有达到核心线程数

        //3>如果没有达到核心线程数,创建新的线程执行任务。如果已经达到优先在队列中存储

        // 直到队列填满,

        //4> 若队列填满后再来新的任务,这时候判断是否达到最大线程数

        //如果没有,创建新的线程执行任务,知道填满最大线程数。

        //5>如果已经填满最大线程数,队列也已经填满,没有空闲的线程,就执行回绝策略。

        //线程池中的线程达到核心线程数或者是超过核心线程数,超出的数量会根据存活时间进行销毁。

        //如果线程数量小于核心线程数,不会消亡。

java中内置的线性池对象

        //可以根据工作任务来创建线程,如果没有空闲的线程就创建新的线程   线程存活时间60s

//        Executors.newCachedThreadPool();

        //设定最大线程数量

//        Executors.newFixedThreadPool(10);

        //提供定时运行的处理方案

//        Executors.newScheduledThreadPool(10);

        //创建一个具有单个线程的线程池  保障任务队列完全按照顺序执行

//        Executors.newSingleThreadExecutor();

代码案例:

BlockingQueue queue = new ArrayBlockingQueue(12);

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(

                5,8,10, TimeUnit.SECONDS,

                queue, Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy()

        );

        Runnable run =()->{

            System.out.println(Thread.currentThread().getName()+"执行代码run");

            try {

                Thread.sleep(2000);

            } catch (InterruptedException e) {

                throw new RuntimeException(e);

            }

            System.out.println(Thread.currentThread().getName()+"执行完毕");

        };

        for(int i = 0; i < 21; i++){

            threadPoolExecutor.execute(run);

        }

        threadPoolExecutor.shutdown();

    }

}

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值