Java多线程 - ReentrantLock实际开发中的应用场景

1. 公平锁,线程排序执行,防饿死应用场景

公平锁原则必须按照锁申请时间上先到先得的原则分配机制场景;

1).实现逻辑 上(包括:软件中函数计算、业务先后流程;硬件中操作实现中顺序逻辑)的顺序排队机制的场景;
软件场景:用户交互View中对用户输入结果分析类,分析过程后面算法依赖上一步结果的场景,例如:推荐算法实现[根据性别、年龄筛选]、阻塞队列的实现;

硬件场景:需要先分析确认用户操作类型硬件版本或者厂家,然后发出操作指令;例如:自动售货机;

2).现实 生活中 时间排序的 公平原则:

例如:客服分配,必须是先到先服务,不能出现饿死现象;公平锁实现见上文:

公平锁与非公平锁的测试demo:逻辑代码实现那就没法子实现了;

阻塞队列的实现就是时间上的公平原则。

2. 非公平锁,效率的体现者

实际开发中最常用的的场景就是非公平锁,ReentrantLock无参构造默认就时候非公平锁;适应场景除了上面公平锁中提到的其他都是非公平锁的使用场景;

3. ReentrantLock.Condition线程通信

ReentrantLock.Condition线程通信是最长见的面试题,这里以最简单例子:两个线程之间交替打印 26英文字母和阿拉伯数字为demo:

private void alternateTask() {
        ReentrantLock lock = new ReentrantLock();
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
        Thread thread1 = new Thread(() -> {
            try {
                lock.lock();
                for (int i = 65; i < 91; i++) {
                    System.out.println("----------thread1------- " + (char) i);
                    condition2.signal();
                    condition1.await();
                }
                condition2.signal();
            } catch (Exception e) {
            } finally {
                lock.unlock();
            }
        });
        Thread thread2 = new Thread(() -> {
            try {
                lock.lock();
                for (int i = 0; i < 26; i++) {
                    System.out.println("----------thread2------- " + i);
                    condition1.signal();
                    condition2.await();
                }
                condition1.signal();
            } catch (Exception e) {
            } finally {
                lock.unlock();
            }
        });
        thread1.start();
        thread2.start();
    }

4.同步功能的使用

实现线程同步锁synchronized 功能【单例为例】

  private Singleton() {
    }

    private static Singleton instance;
    private static Lock lock = new ReentrantLock();

    public static Singleton getInstance() {
        lock.lock();
        try {
            if (instance == null) {
                instance = new Singleton();
            }
        } finally {
            lock.unlock();
        }
        return instance;
    }

5. 中断杀器应用

ReentrantLock中lockInterruptibly()和lock()最大的区别就是中断相应问题:

lock()是支持中断相应的阻塞试的获取方式,因此即使主动中断了锁的持有者,但是它不能立即unlock(),仍然要机械版执行完所有操作才会释放锁。

lockInterruptibly()是 优先响应中断的,这样有个优势就是可以通过tryLock()、tryLock(timeout, TimeUnit.SECONDS)方法,中断优先级低的Task,及时释放资源给优先级更高的Task,甚至看到网上有人说可以做防止死锁的优化;
 

 ReentrantLock lock = new ReentrantLock();
        try {
            lock.lockInterruptibly();
            if (lock.tryLock(timeout, TimeUnit.SECONDS)) {
                //TODO
            }else{
                //超时直接中断优先级低的Task
                Thread.currentThread().interrupt();
                lock.lock();
                //TODO
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
           

6. 非重要任务Lock使用

优先级较低的操作让步给优先级更高的操作,提示代码效率/用户体验;忽略重复触发

1).用在定时任务时,如果任务执行时间可能超过下次计划执行时间,确保该有状态任务只有一个正在执行,忽略重复触发。

2).用在界面交互时点击执行较长时间请求操作时,防止多次点击导致后台重复执行(忽略重复触发)。

以上两种情况多用于进行非重要任务防止重复执行,(如:清除无用临时文件,检查某些资源的可用性,数据备份操作等)

tryLock()功能:如果已经获得锁立即返回fale,起到防止重复而忽略的效果 

ReentrantLock lock = new ReentrantLock();
      //防止重复执行,执行耗时操作,例如用户重复点击
       if (lock.tryLock()) {
           try {
			//TO DO
           } finally {
             lock.unlock();
           }
       }
      

超时放弃

定时操作的例如:错误日志、定时过期缓存清理的操作,遇到优先级更高的操作占用资源时,暂时放弃本次操作下次再处理,可以起到让出CPU,提升用户体验;

  ReentrantLock lock = new ReentrantLock();
        try {
            if (lock.tryLock(timeout, TimeUnit.SECONDS)) {
                //TO DO
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java多线程适用于以下场景: 1. 需要并发处理任务的场景,如Web服务器、数据库管理系统、大数据处理、多媒体处理等。 2. 需要响应用户输入的场景,如GUI应用程序、游戏等。 3. 需要提高程序性能的场景,如CPU密集型计算、IO密集型操作等。 下面是Java多线程的代码例子: 1. 创建线程的方式 方式一:继承Thread类 ```java class MyThread extends Thread { public void run() { System.out.println("Thread is running..."); } } public class Main { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); } } ``` 方式二:实现Runnable接口 ```java class MyRunnable implements Runnable { public void run() { System.out.println("Thread is running..."); } } public class Main { public static void main(String[] args) { MyRunnable runnable = new MyRunnable(); Thread thread = new Thread(runnable); thread.start(); } } ``` 2. 线程同步的方式 方式一:使用synchronized关键字 ```java class Counter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } } public class Main { public static void main(String[] args) { Counter counter = new Counter(); for (int i = 0; i < 10; i++) { Thread thread = new Thread(() -> { for (int j = 0; j < 1000; j++) { counter.increment(); } }); thread.start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Count: " + counter.getCount()); } } ``` 方式二:使用Lock接口 ```java class Counter { private int count = 0; private Lock lock = new ReentrantLock(); public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } public int getCount() { lock.lock(); try { return count; } finally { lock.unlock(); } } } public class Main { public static void main(String[] args) { Counter counter = new Counter(); for (int i = 0; i < 10; i++) { Thread thread = new Thread(() -> { for (int j = 0; j < 1000; j++) { counter.increment(); } }); thread.start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Count: " + counter.getCount()); } } ``` 以上是Java多线程的一些常见应用场景和代码例子。需要注意的是,在编写多线程程序时,一定要注意线程安全性和避免死锁等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值