java
-
java锁
- 公平锁:是指多个线程按照申请锁的顺序来获取锁,类似排队打饭,先来后到
- 非公平锁:是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁在高并发的情况下,有可能会造成优先级反转或者饥饿现象
- 可重入锁(递归锁):指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁,即,线程可以进入任何一个它已经拥有的锁所同步着的代码块(避免死锁)
- 自旋锁:指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少上下文切换的消耗,缺点是循环会消耗CPU
public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; }
- 独占锁(写锁):指该锁一次只能被一个线程所持有。对ReentrantLock和synchronized而言都是独占锁。
- 共享锁(读锁):指该锁可被多个线程所持有。对ReentrantReadWriteLock其读锁是共享锁,其写锁是独占锁。读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。
- 写操作:原子+独占,整个过程必须是一个完整的统一体,中间不许被分割,被打断。
-
(同步工具类) CountDownLatch:锁存器
- countDown()方法:递减锁存器的计数
- await()方法:使当前线程在锁存器倒计时至零之前一直等待,除非线程中断
public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(6); for (int i = 1; i <= 6; i++) { new Thread(() -> { System.out.println(Thread.currentThread().getName() + "\t上完自习,走出教室"); countDownLatch.countDown(); }, String.valueOf(i)).start(); } countDownLatch.await(); System.out.println(Thread.currentThread().getName() + "\t教室里已没人"); } }
-
(同步工具类)CyclicBarrier:循环栅栏
- 作用:让所有线程都等待完成后才会继续下一步行动。场景:集齐7颗龙珠召唤神龙
- 常用构造函数
// 第一个参数:线程数量 // 第二个参数:线程,当所有线程执行完成后才做的动作 public CyclicBarrier(int parties, Runnable barrierAction) { if (parties <= 0) throw new IllegalArgumentException(); this.parties = parties; this.count = parties; this.barrierCommand = barrierAction; }
- await()方法:阻塞线程
public class CyclicBarrierDemo { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> { System.out.println(Thread.currentThread().getName() + "\t#######\t召唤神龙成功"); }); for (int i = 1; i <= 7; i++) { final int tempInt = i; new Thread(() -> { System.out.println(Thread.currentThread().getName() + "\t集齐第" + tempInt + "颗龙珠"); try { cyclicBarrier.await(); } catch (Exception e) { e.printStackTrace(); } }, String.valueOf(i)).start(); } } }
运行结果:
-
Semaphore(信号量)
- 主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制
- 场景:争车位
public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3);// 模拟3个车位 for (int i = 1; i <= 6; i++) { new Thread(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "\t抢到车位"); TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + "\t停车3秒后离开车位"); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } }, String.valueOf(i)).start(); } } }
算法
- 有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/squares-of-a-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法一:暴力排序。每个数平方之后,然后排序
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0, right = nums.length-1;
while (left <= right) {
nums[left] = nums[left] * nums[left];
left++;
}
Arrays.sort(nums);
return nums;
}
}
解法二:双指针法-----数组其实是有序的,只不过负数平方之后可能成为最大数了。那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。具体,i指向最左边,j指向最右边。
定义一个新数组result,和原数组一样大小,让k指向result数组终止位置。
如果A[i] * A[i] < A[j] * A[j] 那么result[k–] = A[j] * A[j]; 。
如果A[i] * A[i] >= A[j] * A[j] 那么result[k–] = A[i] * A[i]; 。
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0, right = nums.length - 1;
int[] result = new int[nums.length];
int index = result.length-1;
while (left <= right) {
if (nums[left] * nums[left] < nums[right] * nums[right]) {
result[index--] = nums[right] * nums[right];
right--;
} else {
result[index--] = nums[left] * nums[left];
left++;
}
}
return result;
}
}