收集了 LeetCode 面试经典150 & LeetCode 热题100中常用的函数与技巧
LeetCode之数组/字符串
public static void main(String[] args) {
// 1. 数组排序
int[] array = new int[]{3, 7, 5, 2};
Arrays.sort(array);
// 结果: [2, 3, 5, 7]
System.out.println(Arrays.toString(array));
// 2. 数组拷贝
int[] arrayOld = new int[]{1, 2, 3, 4, 5};
int[] arrayNew = new int[5];
System.arraycopy(arrayOld, 0, arrayNew, 0, arrayOld.length - 1);
// 结果: [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(arrayOld));
// 结果: [1, 2, 3, 4, 0]
System.out.println(Arrays.toString(arrayNew));
// 3. 最大值最小值
int max = Math.max(2, 3);
int min = Math.min(2, 3);
// 结果 3-2
System.out.println(max + "-" + min);
// 4. 随机数生成
Random random = new Random();
int randomInt = random.nextInt(10);
// 结果: 8
System.out.println(randomInt);
// 5. HashMap
Map<String, String> hashMap = Maps.newHashMap();
hashMap.put("1", "1");
hashMap.put("2", "2");
hashMap.put("3", "3");
// 结果: true
System.out.println(hashMap.containsKey("1"));
// 6. ArrayList
List<String> arrayList = Lists.newArrayList("1", "2", "3");
arrayList.set(2, "4");
arrayList.remove(1);
// 结果: [1, 4]
System.out.println(arrayList);
// 7. 数组创建
int[] arr1 = new int[3];
arr1[0] = 1;
int[] arr2 = {1, 2, 3};
int[] arr3 = new int[]{1,2,3};
// 结果: [1, 0, 0]
System.out.println(Arrays.toString(arr1));
// 结果: [1, 2, 3]
System.out.println(Arrays.toString(arr2));
// 结果: [1, 2, 3]
System.out.println(Arrays.toString(arr3));
// 8. 字符串
String str = "hello world";
char[] charArray = str.toCharArray();
// 结果: l
System.out.println(str.charAt(3));
// 结果: [h, e, l, l, o, , w, o, r, l, d]
System.out.println(Arrays.toString(charArray));
// 9. switch语句
String condition = "a";
// 结果: a
switch (condition) {
case "a":
System.out.println("a");
break;
case "b":
System.out.println("b");
break;
default:
System.out.println("c");
}
// 10. 可变字符串
StringBuilder sb = new StringBuilder();
sb.append("1");
sb.append("2");
sb.append("3");
// 结果: 123
System.out.println(sb.toString());
// 11. 字符串去空格
String strTrim = " tes t ";
String trim = strTrim.trim();
// 结果: tes t
System.out.println(trim);
// 结果: 5
System.out.println(strTrim.lastIndexOf("t"));
// 12. 字符串截取
String strSub = "test subString";
String substring = strSub.substring(5, 8);
System.out.println(substring);
// 13. 正则&字符串拼接
String string = " hello world ";
String trim1 = string.trim();
// 结果: hello world
System.out.println(trim1);
String[] split = trim1.split("\\s+");
List<String> strings = Arrays.asList(split);
// 结果: [hello, world]
System.out.println(strings);
Collections.reverse(strings);
// 结果: [world, hello]
System.out.println(strings);
// 结果: world,hello
String join = String.join(",", strings);
System.out.println(join);
}
LeetCode之双指针
public static void main(String[] args) {
// 1. Char操作
char a = '1';
char b = 'b';
// 判断是否字符或数组
// 结果: true
System.out.println(Character.isLetter(b));
// 结果: true
System.out.println(Character.isDigit(a));
// 结果: true
System.out.println(Character.isLetterOrDigit(a));
char c = 'C';
// 结果: true
System.out.println(Character.toLowerCase(c));
// 2. 可变字符串反转
StringBuilder sb = new StringBuilder();
sb.append("1");
sb.append("2");
sb.append("3");
// 结果: 321
System.out.println(sb.reverse());
}
LeetCode之滑动窗口
public static void main(String[] args) {
// 1. Integer最大最小值
int min = Integer.MIN_VALUE;
int max = Integer.MAX_VALUE;
// 结果: -2147483648
System.out.println(min);
// 结果: 2147483648
System.out.println(max);
// 2. Set操作
Set<String> set = Sets.newHashSet("1", "2", "2", "3");
// 结果: [1, 2, 3]
System.out.println(set);
// 结果: true
System.out.println(set.contains("2"));
// 结果: true
System.out.println(set.remove("3"));
// 结果: [1, 2]
System.out.println(set);
}
LeetCode之矩阵
public static void main(String[] args) {
// 1. 字母索引
char a = 'a';
char b = 'b';
// 结果: 49
System.out.println(a - '0');
// 结果: 50
System.out.println(b - '0');
// 2. 深拷贝
int[] aArr = new int[]{1, 2, 3};
int[] clone = aArr.clone();
clone[0] = 11;
// 结果: [1, 2, 3]
System.out.println(Arrays.toString(aArr));
// 结果: [11, 2, 3]
System.out.println(Arrays.toString(clone));
}
LeetCode之哈希表
public static void main(String[] args) {
// 1. Map操作
Map<Integer, String> map = new HashMap<>();
map.put(1, "1");
map.put(2, "2");
// 结果: 3
System.out.println(map.getOrDefault(3, "3"));
// 结果: true
System.out.println(map.containsKey(1));
Collection<String> values = map.values();
// 结果: [1, 2]
System.out.println(values);
List<String> list = new ArrayList<>(values);
// 结果: [1, 2]
System.out.println(list);
// 2. Set操作
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
// 结果: true
System.out.println(set.contains(1));
// 3. 字符串char操作
String str = "hello";
char[] chars = str.toCharArray();
// 结果: [h, e, l, l, o]
System.out.println(Arrays.toString(chars));
// 结果: e
System.out.println(str.charAt(1));
// 4. 字符串分割
String s = "dog cat cat dog";
String[] s1 = s.split(" ");
// 结果: [dog, cat, cat, dog]
System.out.println(Arrays.toString(s1));
// 5. 最大最小值
int max = Math.max(2, 3);
int min = Math.min(1, 2);
// 结果: 3
System.out.println(max);
// 结果: 1
System.out.println(min);
// 6. 除法操作
// 结果: 3
System.out.println(6 / 2);
// 结果: 0
System.out.println(6 % 2);
// 结果: 2
System.out.println(5 / 2);
// 结果: 1
System.out.println(5 % 2);
}
LeetCode之区间
public static void main(String[] args) {
// 1. StringBuilder
StringBuilder sb = new StringBuilder(Integer.toString(1));
sb.append("2");
// 结果: 12
System.out.println(sb.toString());
// 2. Arrays
int[] arr = new int[]{3, 1, 2, 4};
Arrays.sort(arr);
// 结果: [1, 2, 3, 4]
System.out.println(Arrays.toString(arr));
int[][] arr1 = new int[][]{{2, 1}, {1, 2}, {3, 0}};
// 结果: [[3, 0], [2, 1], [1, 2]]
Arrays.sort(arr1, (a, b) -> b[0] - a[0]);
System.out.println(Arrays.deepToString(arr1));
// 结果: [[1, 2], [2, 1], [3, 0]]
Arrays.sort(arr1, (a, b) -> a[0] - b[0]);
System.out.println(Arrays.deepToString(arr1));
// 3. List
List<int[]> list = new ArrayList<>();
list.add(new int[]{1, 2});
list.add(new int[]{3, 4});
int[][] arr2 = list.toArray(new int[1][1]);
// 结果: [[1, 2], [3, 4]]
System.out.println(Arrays.deepToString(arr2));
}
LeetCode之栈
public static void main(String[] args) {
// 双端队列
Deque<Character> stack = new ArrayDeque<>();
stack.push('1');
stack.push('2');
// 结果: 2
System.out.println(stack.peek());
// 结果: 2
System.out.println(stack.pop());
// 结果: false
System.out.println(stack.isEmpty());
// 结果: 1
System.out.println(stack.pop());
// 结果: true
System.out.println(stack.isEmpty());
// Character
String str = "test";
char[] chars = str.toCharArray();
// 结果: t
System.out.println(str.charAt(0));
// 结果: [t, e, s, t]
System.out.println(Arrays.toString(chars));
// 双端队列
Deque<Character> deque = new LinkedList<>();
// 从左右往右offer
deque.offerFirst('1');
deque.offerFirst('2');
deque.offerFirst('3');
deque.push('4');
deque.offerLast('5');
// 结果: [4, 3, 2, 1, 5]
System.out.println(deque);
deque.pollFirst();
// 结果: [3, 2, 1, 5]
System.out.println(deque);
deque.pollLast();
// 结果: [3, 2, 1]
System.out.println(deque);
// Integer
String str1 = Integer.toString(1);
// 结果: 1
System.out.println(str1);
int i = Integer.parseInt("2");
// 结果: 2
System.out.println(i);
}
LeetCode之链表
static class ListNode {
// 节点的值
int val;
// 指向下一个节点的指针
ListNode next;
// 默认构造函数
ListNode() {}
// 带值的构造函数
ListNode(int x) {
this.val = x;
}
// 带值和下一个节点的构造函数
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public static void main(String[] args) {
// Set
Set<ListNode> set = new HashSet<>();
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
node1.next = node2;
set.add(node1);
set.add(node2);
// 结果: true
System.out.println(set.contains(node1));
// dummyNode
ListNode dummyNode = new ListNode(-1);
ListNode node3 = new ListNode(3);
dummyNode.next = node3;
// 当前节点初始化为哨兵节点
ListNode cur = dummyNode;
// 结果: -1
System.out.println(cur.val);
// 结果: 3
System.out.println(cur.next.val);
}
LeetCode之二叉树
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public static void main(String[] args) {
TreeNode root = new TreeNode(0);
TreeNode treeNode1 = new TreeNode(1);
TreeNode treeNode2 = new TreeNode(2);
root.left = treeNode1;
root.right = treeNode2;
}
LeetCode之二叉树层次遍历
public static void main(String[] args) {
// 队列
Queue<Integer> queue = new ArrayDeque<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
// 结果: [1, 2, 3]
System.out.println(queue);
// 结果: 1 左头右尾
System.out.println(queue.peek());
// 结果: 1
System.out.println(queue.poll());
// 结果: [2, 3]
System.out.println(queue);
// 双端队列
Deque<Integer> deque = new ArrayDeque<>();
deque.offer(1);
// 左头右尾
deque.offerLast(2);
// 结果: [1, 2]
System.out.println(deque);
deque.offerFirst(3);
// 结果: [3, 1, 2]
System.out.println(deque);
deque.pollLast();
// 结果: [3, 1]
System.out.println(deque);
deque.pollFirst();
// 结果: [1]
System.out.println(deque);
}
LeetCode之二叉搜索树
public static void main(String[] args) {
// 最大最小值
// 结果: -2147483648
System.out.println(Integer.MIN_VALUE);
// 结果: 2147483647
System.out.println(Integer.MAX_VALUE);
// 结果: -9223372036854775808
System.out.println(Long.MIN_VALUE);
// 结果: 9223372036854775807
System.out.println(Long.MAX_VALUE);
// 结果: 1
System.out.println(Math.min(1, 2));
// 结果: 2
System.out.println(Math.max(1, 2));
}
LeetCode之图
public static void main(String[] args) {
// 图
int[][] grid = new int[][]{{1, 2, 3}, {4, 5, 6}};
// 结果: [[1, 2, 3], [4, 5, 6]]
System.out.println(Arrays.deepToString(grid));
// 结果: 2
System.out.println(grid.length);
// 结果: 3
System.out.println(grid[0].length);
// HashMap
Map<Integer, String> map = new HashMap<>();
map.put(1, "1");
map.put(2, "2");
map.put(3, "3");
// 结果: true
System.out.println(map.containsKey(1));
// 结果: false
System.out.println(map.containsValue(4));
// 结果: null;
System.out.println(map.putIfAbsent(4, "4"));
for (Map.Entry<Integer, String> item : map.entrySet()) {
System.out.println(item.getKey());
System.out.println(item.getValue());
}
}
LeetCode之图的广度优先搜索
public static void main(String[] args) {
// 1. Set
String[] str = new String[]{"1", "2", "2", "3"};
List<String> list = Arrays.asList(str);
// 结果: [1, 2, 2, 3]
System.out.println(list);
Set<String> set = new HashSet<>(list);
// 结果: [1, 2, 3]
System.out.println(set);
// 结果: true
System.out.println(set.contains("1"));
set.remove("1");
// 结果: false
System.out.println(set.contains("1"));
// 2. 队列,先进先出
Queue<Integer> queue = new LinkedList<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
// 结果: [1, 2, 3]
System.out.println(queue);
queue.poll();
// 结果: [2, 3]
System.out.println(queue);
// 结果: 2
System.out.println(queue.size());
// 结果: false
System.out.println(queue.isEmpty());
// 3. String
String str1 = "hello";
StringBuilder sb = new StringBuilder(str1);
// 结果: hello
System.out.println(sb);
sb.setCharAt(1, 'w');
// 结果: hwllo
System.out.println(sb.toString());
}
LeetCode之字典树
public static void main(String[] args) {
// 1. Character
String str = "abcde";
char[] charArr = str.toCharArray();
List<Integer> list = new ArrayList<>();
for (char item : charArr) {
int i = item - 'a';
list.add(i);
}
// 结果: [0, 1, 2, 3, 4]
System.out.println(list);
// 结果: a
System.out.println(str.charAt(0));
}
LeetCode之回溯
public static void main(String[] args) {
// 1. Character
String str = "hello";
StringBuilder sb = new StringBuilder(str);
// 结果: h
System.out.println(str.charAt(0));
sb.deleteCharAt(1);
// 结果: hllo
System.out.println(sb);
// 2. List
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
// 结果: [1, 2, 3]
System.out.println(list);
list.remove(list.size() - 1);
// 结果: [1, 2]
System.out.println(list);
// 3. Deque
Deque<Integer> deque = new LinkedList<>();
deque.addLast(1);
deque.addLast(2);
deque.addFirst(0);
deque.addLast(3);
// 结果: [0, 1, 2, 3]
System.out.println(deque);
deque.removeLast();
List<Integer> list1 = new ArrayList<>(deque);
// 结果: [0, 1, 2]
System.out.println(list1);
list1.remove(1);
// 结果: [0, 2]
System.out.println(list1);
// 4. StringBuilder
StringBuilder sb1 = new StringBuilder("hello");
// 结果: hello
System.out.println(sb1);
sb1.deleteCharAt(sb1.length() - 1);
// 结果: hell
System.out.println(sb1);
}
LeetCode之分治
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode() {
}
public TreeNode(int val) {
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
static class ListNode {
int val;
ListNode next;
public ListNode() {}
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public static void main(String[] args) {
// 1. 中间值计算
int left = 1;
int right = 5;
// 结果: 3 此方式可能会数组越界
System.out.println((left + right) / 2);
// 结果: 3 右移1位相当于除以2
System.out.println((left + right) >> 1);
// 结果: 3
System.out.println((right - left) / 2 + left);
// 2. 排序
List<String> list = Lists.newArrayList("1", "5", "3", "0");
// 结果: [1, 5, 3, 0]
System.out.println(list);
Collections.sort(list);
// 结果: [0, 1, 3, 5]
System.out.println(list);
}
LeetCode之二分查找
public static void main(String[] args) {
// 1. 中间值计算
int left = 1;
int right = 5;
// 结果: 3 此方式可能会数组越界
System.out.println((left + right) / 2);
// 结果: 3 右移1位相当于除以2
System.out.println((left + right) >> 1);
// 结果: 3
System.out.println((right - left) / 2 + left);
// 2. 二分查找
int[] nums = new int[]{1, 2, 3, 4};
int target = 2;
while (left <= right) {
int mid = (left + right) / 2;
if (target <= nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
// 3. 最大最小值
int min = Math.min(1, 2);
int max = Math.max(1, 2);
// 结果: 1
System.out.println(min);
// 结果: 2
System.out.println(max);
}
LeetCode之堆
public static void main(String[] args) {
// 1. 优先级队列,会给队列自动排序,头部最小
PriorityQueue<Integer> queue = new PriorityQueue<>(1);
queue.offer(5);
queue.offer(1);
queue.offer(3);
queue.offer(2);
queue.offer(4);
// 结果: [1, 2, 3, 5, 4]
System.out.println(queue);
// 结果: 1
System.out.println(queue.peek());
queue.poll();
// 结果: [2, 4, 3, 5]
System.out.println(queue);
// 2. 优先级队列,会给队列自动排序,(降序)头部最大
PriorityQueue<Integer> queue1 = new PriorityQueue<>(Comparator.reverseOrder());
queue1.offer(5);
queue1.offer(1);
queue1.offer(3);
queue1.offer(2);
queue1.offer(4);
// 结果: [5, 4, 3, 1, 2]
System.out.println(queue1);
// 结果: 5
System.out.println(queue1.peek());
queue1.poll();
// 结果: [4, 2, 3, 1]
System.out.println(queue1);
// 3. 数组
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] + a[1] - b[0] - b[1]);
pq.offer(new int[]{1, 2});
pq.offer(new int[]{0, 1});
pq.offer(new int[]{2, 3});
List<String> list = new ArrayList<>();
for (int[] ints : pq) {
list.add(Arrays.toString(ints));
}
// 结果: [[0, 1], [1, 2], [2, 3]]
System.out.println(list);
// 4. List
// 结果: [1, 2, 3]
System.out.println(Lists.newArrayList("1", "2", "3"));
}
LeetCode之位运算
public static void main(String[] args) {
// 1、StringBuilder
StringBuilder sb = new StringBuilder("abc");
// 结果: cba
System.out.println(sb.reverse());
// 结果: 49
System.out.println('a' - '0');
// 结果: 50
System.out.println('b' - '0');
// 结果: 51
System.out.println('c' - '0');
// 结果: 2
System.out.println('c' - 'a');
// 2、位操作 取出 3 的最低位
// 结果: 1
System.out.println(3 & 1);
// 3、异或
// 异或运算的特性是:相同的数字相互抵消
// 0 与 任何数字异或都等于该数字
// 结果: 0
System.out.println( 5 ^ 5);
// 结果: 5
System.out.println(0 ^ 5);
}
LeetCode之数学
public static void main(String[] args) {
// 1、String
String str = String.valueOf(123);
StringBuilder sb = new StringBuilder(str);
System.out.println(sb.reverse().toString());
// 2、double
System.out.println(2 / 1.0);
System.out.println(2 % 1.0);
}
LeetCode之一维动态规划
public static void main(String[] args) {
// 1、最大最小值
int min = Math.min(1, 2);
int max = Math.max(1, 2);
// 结果: 1
System.out.println(min);
// 结果: 2
System.out.println(max);
// 2、Set
Set<String> set = new HashSet<>();
set.add("1");
set.add("2");
// 结果: true
System.out.println(set.contains("1"));
// 3、Array
int[] arr = new int[5];
// 结果: [0, 0, 0, 0, 0]
System.out.println(Arrays.toString(arr));
Arrays.fill(arr, 1);
// 结果: [1, 1, 1, 1, 1]
System.out.println(Arrays.toString(arr));
}
LeetCode之多维动态规划
public static void main(String[] args) {
// 1、CharArray
String str = "abcde";
char[] chars = str.toCharArray();
// 结果: [a, b, c, d, e]
System.out.println(Arrays.toString(chars));
// 结果: a
System.out.println(str.charAt(0));
// 结果: bcd
System.out.println(str.substring(1, str.length() - 1));
// 2、最大最小值
// 结果: 1
System.out.println(Math.min(1, 2));
// 结果: 4
System.out.println(Math.max(2, 4));
}
LeetCode之多线程
// 1. 基础Thread类
static class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running: " + Thread.currentThread().getName());
}
public static void main(String[] args) {
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
// 启动线程1 结果: Thread is running: Thread-0
thread1.start();
// 启动线程2 结果: Thread is running: Thread-1
thread2.start();
}
}
// 2. 实现Runnable接口
static class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread is running: " + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread thread1 = new Thread(new MyRunnable());
Thread thread2 = new Thread(new MyRunnable());
// 使用Lambda表达式简化Runnable的实现
Thread thread3 = new Thread(() -> System.out.println("Thread is running: " + Thread.currentThread().getName()));
// 启动线程1 结果: Thread is running: Thread-0
thread1.start();
// 启动线程2 结果: Thread is running: Thread-1
thread2.start();
// 启动线程3 结果: Thread is running: Thread-2
thread3.start();
}
}
// 3. 实现Callable接口
static class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("Thread is running: " + Thread.currentThread().getName());
return Thread.currentThread().getName();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable myCallable = new MyCallable();
// FutureTask实现了RunnableFuture接口,而RunnableFuture接口同时继承了Runnable接口和Future接口
FutureTask<String> futureTask = new FutureTask<>(myCallable);
Thread thread = new Thread(futureTask);
// 启动线程 结果: Thread is running: Thread-0
thread.start();
// 结果: Thread-0
System.out.println(futureTask.get());
}
}
// 4. 线程池方式
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4,
4,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(20000),
new ThreadPoolExecutor.CallerRunsPolicy());
Runnable task1 = () -> System.out.println("task1 is running: " + Thread.currentThread().getName());
Runnable task2 = () -> System.out.println("task2 is running: " + Thread.currentThread().getName());
Callable<String> task3 = () -> {
System.out.println("task3 is running: " + Thread.currentThread().getName());
return Thread.currentThread().getName();
};
// Runnable无返回值,异常处理简单;Callable有返回值,异常处理更加灵活,使用submit()提交,返回一个Future对象,用于获取任务的结果
// 提交任务1 结果: task1 is running: pool-1-thread-1
threadPoolExecutor.execute(task1);
// 提交任务2 结果: task2 is running: pool-1-thread-2
threadPoolExecutor.submit(task2);
// 提交任务3 结果: task3 is running: pool-1-thread-3
Future<String> submit = threadPoolExecutor.submit(task3);
// 结果: pool-1-thread-3
System.out.println(submit.get());
}
/**
* CountDownLatch 适用于需要等待其他线程完成某些操作后再继续的场景
* 主线程等待3个工作线程完成后再继续执行
* 结果
* <p>
* Thread-0 is working.
* Thread-1 is working.
* Thread-2 is working.
* Thread-0 finished work.
* Thread-1 finished work.
* Thread-2 finished work.
* Main thread resumes after all workers finished.
*/
public static void main1(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " is working.");
// 工作完成,计数减一
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName() + " finished work.");
}).start();
}
// 等待计数为0
countDownLatch.await();
System.out.println("Main thread resumes after all workers finished.");
}
/**
* 限制同时访问共享资源的线程数量
* <p>
* 结果
* Thread-0 is working.
* Thread-1 is working.
* Thread-0 finished work.
* Thread-1 finished work.
* Thread-2 is working.
* Thread-3 is working.
* Thread-2 finished work.
* Thread-3 finished work.
* Thread-4 is working.
* Thread-4 finished work.
*/
public static void main2(String[] args) {
// 允许
Semaphore semaphore = new Semaphore(2);
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
// 获取许可(如果当前可用的许可证(计数器值)大于 0,许可证计数减少 1,线程可以继续执行)
// 如果没有可用的许可证(计数器值为 0),线程将被阻塞,直到其他线程释放许可证
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " is working.");
// 模拟工作
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " finished work.");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放许可
// 许可证计数器增加 1,表示有一个新的许可证可用
// 如果有任何被阻塞的线程正在等待许可证,它们会被唤醒,重新尝试获取许可证
semaphore.release();
}
}).start();
}
}
/**
* 多个线程在一处同时执行,所有线程到达后再继续
* 结果
* <p>
* Thread-0 is at the barrier.
* Thread-1 is at the barrier.
* Thread-2 is at the barrier.
* All threads reached the barrier, continuing execution.
* Thread-2 has crossed the barrier.
* Thread-1 has crossed the barrier.
* Thread-0 has crossed the barrier.
*/
public static void main3(String[] args) {
// 当所有线程到达时执行
CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> System.out.println("All threads reached the barrier, continuing execution."));
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " is at the barrier.");
// 等待其他线程到达
try {
cyclicBarrier.await();
} catch (Exception e) {
System.out.println("cyclicBarrier catch error" + e);
}
System.out.println(Thread.currentThread().getName() + " has crossed the barrier.");
}).start();
}
}
/**
* wait()和notify()
* 结果
* Produced: 0
* Consumed: 0
* Produced: 1
* Consumed: 1
* Produced: 2
* Consumed: 2
* Produced: 3
* Consumed: 3
* Produced: 4
* Consumed: 4
*/
private static final Object lock = new Object();
private static boolean ready = false;
public static void main4(String[] args) {
Thread producer = new Thread(() -> {
synchronized (lock) {
for (int i = 0; i < 5; i++) {
while (ready) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ready = true;
System.out.println("Produced: " + i);
lock.notifyAll();
}
}
});
Thread consumer = new Thread(() -> {
synchronized (lock) {
for (int i = 0; i < 5; i++) {
while (!ready) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ready = false;
System.out.println("Consumed: " + i);
lock.notifyAll();
}
}
});
producer.start();
consumer.start();
}
private static final Lock lock1 = new ReentrantLock();
private static final Condition condition = lock1.newCondition();
/**
* await()和signal()
* 结果
* Produced: 0
* Consumed: 0
* Produced: 1
* Consumed: 1
* Produced: 2
* Consumed: 2
* Produced: 3
* Consumed: 3
* Produced: 4
* Consumed: 4
*/
public static void main(String[] args) {
Thread producer = new Thread(() -> {
lock1.lock();
try {
for (int i = 0; i < 5; i++) {
while (ready) {
condition.await();
}
ready = true;
System.out.println("Produced: " + i);
condition.signalAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock1.unlock();
}
});
Thread consumer = new Thread(() -> {
lock1.lock();
try {
for (int i = 0; i < 5; i++) {
while (!ready) {
condition.await();
}
ready = false;
System.out.println("Consumed: " + i);
condition.signalAll();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock1.unlock();
}
});
producer.start();
consumer.start();
}