Default Changelist

AioServer.java
FactoryAndStrategy.java
LeetCode25.java
LeetCode49.java
LeetCode61.java
LeetCode71.java
LeetCode73.java
LeetCode114.java
LeetCode141.java
LeetCode228.java
LeetCode289.java
LeetCode290.java
LeetCode703.java
SingletonPattern.java
ThreadDemo1.java

AndStrategy类,使用策略模式优化支付方式。

这些更改包括对单例模式的实现、线程控制的改进、LeetCode问题的解决以及设计模式的应用。
This commit is contained in:
whaifree 2024-09-24 10:09:45 +08:00
parent 33dffb6b07
commit 6d49b27147
15 changed files with 1164 additions and 2 deletions

View File

@ -0,0 +1,58 @@
package cn.whaifree.designPattern.Factory;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 21:14
* @注释
*/
public class FactoryAndStrategy {
public static void main(String[] args) {
Factory factory = new Factory();
Pay pay = factory.getPay(PayType.WX);
pay.pay(100);
Pay pay2 = factory.getPay(PayType.WX);
pay2.pay(200);
}
interface Pay{
void pay(int price);
}
static class WxPay implements Pay {
@Override
public void pay(int price) {
System.out.println("微信支付:" + price);
}
}
static class AliPay implements Pay {
@Override
public void pay(int price) {
System.out.println("支付宝支付:" + price);
}
}
static class Factory{
public Pay getPay(PayType payType){
return payType.pay;
}
}
enum PayType {
WX(new WxPay()),
ALI(new AliPay()), // 单例
;
private Pay pay;
PayType(Pay pay) {
this.pay = pay;
}
}
}

View File

@ -3,13 +3,42 @@ package cn.whaifree.designPattern;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Scanner; import java.util.Scanner;
import java.util.function.BiConsumer;
public class SingletonPattern { public class SingletonPattern {
static class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
static class HungrySingleton {
private static final HungrySingleton instance = new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return instance;
}
}
} }
class Main{ class Main{
public static void main(String[] args) { public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); Scanner scanner = new Scanner(System.in);

View File

@ -0,0 +1,87 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 14:56
* @注释
*/
public class LeetCode228 {
public static void main(String[] args) throws IOException {
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(Paths.get("D:\\project\\LeetCode\\README.md"), StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Future<Integer> result = fileChannel.read(buffer, 0);
while (!result.isDone()) {
// do something
}
}
@Test
public void test() {
int[] nums = {0, 2};
System.out.println(new Solution().summaryRanges(nums));
}
class Solution {
// public List<String> summaryRanges(int[] nums) {
// List<String> path = new ArrayList<>();
// List<String> res = new ArrayList<>();
// for (int i = 1; i < nums.length; i++) {
// if (nums[i] != nums[i - 1]) {
// StringBuilder str = new StringBuilder();
// for (int j = 0; j < path.size()-1; j++) {
// str.append(path.get(j));
// str.append("->");
// }
// str.append(path.get(path.size() - 1));
// path.clear();
// }
// path.add(String.valueOf(nums[i]));
// }
// }
public List<String> summaryRanges(int[] nums) {
List<String> res = new ArrayList<>();
int left = 0;
int right = 1;
while (right < nums.length) {
if (nums[right] != nums[right - 1] + 1) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(nums[left]);
if (left != right - 1) {
stringBuilder.append("->");
stringBuilder.append(nums[right - 1]);
}
res.add(stringBuilder.toString());
left = right;
}
right++;
}
if (left < nums.length) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(nums[left]);
if (left != right - 1) {
stringBuilder.append("->");
stringBuilder.append(nums[right - 1]);
}
res.add(stringBuilder.toString());
}
return res;
}
}
}

View File

@ -0,0 +1,102 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/23 11:08
* @注释
*/
public class LeetCode289 {
@Test
public void test() {
int[][] board = new int[][]{{0, 1, 0}, {0, 0, 1}, {1, 1, 1}, {0, 0, 0}};
new Solution().gameOfLife(board);
for (int[] ints : board) {
System.out.println(Arrays.toString(ints));
}
}
class Solution {
/**
* 为了保证当前修改后的状态不会影响下一个状态的判定设置另外的状态
* 如题所示只有三种
* 1. 如果当前是活细胞但是变成了死细胞那么设置为-1
* 2. 如果当前是活细胞仍然是活细胞那么不变仍为1
* 3. 如果当前是死细胞但是变成了活细胞那么设置为2
* 那么最后遍历修改完状态之后-1修改回为02修改回为1
* @param board
*/
public void gameOfLife(int[][] board) {
//设置方向来遍历某个节点周围的另外几个节点
int[] ner = new int[]{-1,0,1};
//获取行和列
int rows = board.length;
int cols = board[0].length;
//遍历每一个节点格子
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
//设置当前节点周围的存活细胞的数量
int liveNer = 0;
/**
* 当前节点是[ i , j ]
* [i-1,j-1] [i-1,j] [i-1,j+1]
* [ i ,j-1] [ i ,j] [ i ,j+1]
* [i+1,j-1] [i+1,j] [i+1,j+1]
* 那么以当前节点为中心要求周围的节点则最多是3*3形式
* 并且所有的行和列都是用当前节点+1或者-1或者不变构成
* 所以我们设置 ner = {-1,0,1} 来形成遍历
*/
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//必须保证不计算当前节点(不计算自己)
if (!(ner[i]==0 && ner[j]==0)){
//当前节点的相邻节点坐标
int r = row+ner[i];
int c = col+ner[j];
/**判断当前周围节点的存活状态要求满足两个状态
* 1. 必须保证要在 board 矩阵中
* 2. 并且**起始状态要是存活则当前状态为1或者-1都可以(因为这两个状态都表示起始状态为活细胞)**
**/
if ((r >= 0 && r < rows) && (c >= 0 && c < cols) && (Math.abs(board[r][c]) == 1)) {
// -1和1 初始状态都是活细胞
liveNer++;
}
}
}
}
/**开始判断当前节点的存活状态
* 因为遍历到当前节点的时候还没有开始修改细胞状态所以还是0和1的细胞状态
* 那么只需要判断状态变化的即可否则状态不变
**/
if ((board[row][col]==1) && ( liveNer>3 || liveNer<2)){
// -1 代表这个细胞过去是活的现在死了
board[row][col]=-1;
}
if (board[row][col]==0 && ( liveNer==3)){
// 2 代表这个细胞过去是死的现在活了
board[row][col]=2;
}
}
}
//再把额外的状态修改回去
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (board[row][col] == 2) {
board[row][col] = 1;
}
if (board[row][col] == -1){
board[row][col] = 0;
}
}
}
}
}
}

View File

@ -0,0 +1,51 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.util.PriorityQueue;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 15:14
* @注释
*/
public class LeetCode703 {
@Test
public void test() {
KthLargest kthLargest = new KthLargest(3, new int[]{});
System.out.println(kthLargest.add(3));
System.out.println(kthLargest.add(5));
System.out.println(kthLargest.add(10));
System.out.println(kthLargest.add(9));
System.out.println(kthLargest.add(4));
}
class KthLargest {
PriorityQueue<Integer> priorityQueue = null;
int size = 0;
// 小顶堆 第k
public KthLargest(int k, int[] nums) {
priorityQueue = new PriorityQueue<>();
this.size = k;
for (int num : nums) {
priorityQueue.offer(num);
if (priorityQueue.size() > k) {
priorityQueue.poll();
}
}
}
public int add(int val) {
priorityQueue.offer(val);
if (priorityQueue.size() > size) {
priorityQueue.poll();
}
return priorityQueue.peek();
}
}
}

View File

@ -0,0 +1,52 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/23 9:18
* @注释
*/
public class LeetCode73 {
@Test
public void test() {
int[][] matrix = new int[][]{{1, 1, 1}, {1, 0, 1}, {1, 1, 1}};
new Solution().setZeroes(matrix);
for (int[] ints : matrix) {
System.out.println(Arrays.toString(ints));
}
}
class Solution {
public void setZeroes(int[][] matrix) {
int yLen = matrix.length;
boolean[] row = new boolean[yLen];
int xLen = matrix[0].length;
boolean[] col = new boolean[xLen];
for (int y = 0; y < yLen; y++) {
for (int x = 0; x < xLen; x++) {
if (matrix[y][x] == 0) {
row[y] = true;
col[x] = true;
}
}
}
for (int y = 0; y < yLen; y++) {
for (int x = 0; x < xLen; x++) {
if (row[y] || col[x]) {
matrix[y][x] = 0;
}
}
}
}
}
}

View File

@ -0,0 +1,49 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 13:09
* @注释
*/
public class LeetCode290 {
@Test
public void test() {
String pattern = "abbc";
String s = "dog cat cat dog";
System.out.println(new Solution().wordPattern(pattern, s));
}
class Solution {
public boolean wordPattern(String pattern, String s) {
Map<Character, String> map = new HashMap<>();
Map<String, Character> map2 = new HashMap<>();
s = s.trim();
String[] split = s.split(" ");
if (pattern.length() != split.length) {
return false;
}
int len = pattern.length();
for (int i = 0; i < len; i++) {
char key1 = pattern.charAt(i);
String key2 = split[i];
if (!map.containsKey(key1)) {
map.put(key1, key2);
}
if (!map2.containsKey(key2)) {
map2.put(key2, key1);
}
if (!map.get(key1).equals(key2) || map2.get(key2) != key1) {
return false;
}
}
return true;
}
}
}

View File

@ -0,0 +1,128 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 13:22
* @注释
*/
public class LeetCode49 {
@Test
public void test() {
String[] strs = {"eat", "tea", "tan", "ate", "nat", "bat"};
System.out.println(new Solution().groupAnagrams(strs));
}
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
char[] charArray = str.toCharArray(); // 排序后 key 一样
Arrays.sort(charArray);
String key = new String(charArray);
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(str);
}
return new ArrayList<>(map.values());
}
}
class Solution1 {
/**
* 统计每个字母出现的个数并按照a2b1c4这种格式变成String作为key
*
* 统计次数ON*M
* @param strs
* @return
*/
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> res = new ArrayList<>();
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
int[] count = new int[26];
for (int i = 0; i < str.length(); i++) {
int index = str.charAt(i) - 'a';
count[index]++;
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < count.length; i++) {
if (count[i] != 0) {
// a12b19这种形式
stringBuilder.append((char) ('a' + i));
stringBuilder.append(count[i]);
}
}
String key = stringBuilder.toString();
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(str);
}
return new ArrayList<>(map.values());
}
}
//
// class Solution {
//
// static List<Integer> anagrams = null;
// static List<List<String>> res = null;
// public List<List<String>> groupAnagrams(String[] strs) {
// int[][] nums = new int[strs.length][26];
// for (int i = 0; i < strs.length; i++) {
// String str = strs[i];
// for (int j = 0; j < str.length(); j++) {
// nums[i][str.charAt(j) - 'a']++;
// }
// }
//
// anagrams = new ArrayList<>();
// res = new ArrayList<>();
// backTracking(strs, nums, 0);
// return res;
// }
//
// public static void backTracking(String[] strs, int[][] map, int start) {
// if (start >= map.length - 1) {
// List<String> anagram = new ArrayList<>();
// for (Integer a : anagrams) {
// anagram.add(strs[a]);
// }
// res.add(new ArrayList<>(anagram));
// return;
// }
//
// if (!anagrams.isEmpty() && !match(map, anagrams.get(anagrams.size() - 1), start)) {
// return;
// }
//
// for (int i = start; i < map.length; i++) {
// anagrams.add(i);
// backTracking(strs, map, i + 1);
// anagrams.remove(anagrams.size() - 1);
// }
//
// }
//
// public static boolean match(int[][] map, int a, int b) {
// int[] A = map[a];
// int[] B = map[b];
// for (int i = 0; i < 26; i++) {
// if (A[i] != B[i]) return false;
// }
// return true;
// }
// }
}

View File

@ -0,0 +1,42 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/23 12:54
* @注释
*/
public class LeetCode141 {
@Test
public void test() {
ListNode listNode = ListNode.listNodeFromArray(new int[]{1});
// listNode.next.next.next = listNode;
System.out.println(new Solution().hasCycle(listNode));
}
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null) {
return false;
}
if (head.next == null) {
return false; // 只有一个节点
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
}

View File

@ -0,0 +1,62 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/23 13:43
* @注释
*/
public class LeetCode25 {
@Test
public void test() {
ListNode head = ListNode.listNodeFromArray(new int[]{1, 2, 3, 6, 7, 8, 9, 20});
// new Solution().reverse(null, head, 3).printList();
new Solution().reverseKGroup(head, 2).printList();
}
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode pre = new ListNode(-1, head);
return reverseRange(pre.next, k);
}
/**
* pre往后k个元素翻转
* @param pre
* @param k
* @return
*/
public ListNode reverseRange(ListNode pre, int k) {
ListNode index = pre;
ListNode nextNode = pre;
int i = 0;
while (i < k && nextNode != null) {
nextNode = nextNode.next;
i++;
}
if (i < k) {
return pre;
}
ListNode reverseAfterHead = reverse(null, index, k);
index.next = reverseRange(nextNode, k);
return reverseAfterHead;
}
public ListNode reverse(ListNode pre, ListNode after,int k) {
if (k <= 0) {
return pre;
}
if (after == null) {
return pre;
}
ListNode next = after.next;
after.next = pre;
return reverse(after, next, k - 1);
}
}
}

View File

@ -0,0 +1,107 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/23 14:25
* @注释
*/
public class LeetCode61 {
@Test
public void test() {
ListNode head = ListNode.listNodeFromArray(new int[]{1,2,3});
new Solution().rotateRight(head, 3).printList();
}
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if (head == null) {
return null;
}
int len = 0;
ListNode tmpHead = head;
while (tmpHead!= null) {
len++;
tmpHead = tmpHead.next;
}
k %= len;
if (k == 0) {
return head;
}
ListNode pre = new ListNode(-1, head);
ListNode indexPre = pre;
ListNode indexAfter = pre;
for (int i = 0; i < k ; i++) {
indexAfter = indexAfter.next;
}
while (indexAfter.next != null) {
indexAfter = indexAfter.next;
indexPre = indexPre.next;
}
ListNode tmp = indexPre.next;
indexPre.next = null;
indexAfter.next = pre.next;
pre.next = tmp;
return pre.next;
}
}
@Test
public void tes1t() {
ListNode listNode = ListNode.listNodeFromArray(new int[]{1,2,3});
new Solution2().rotateRight(listNode, 4).printList();
}
class Solution1 {
// public ListNode rotateRight(ListNode head, int k) {
// ListNode pre = new ListNode(-1, head);
// ListNode preIndex = pre;
// ListNode afterIndex = pre;
// for (int i = 0; i < k && afterIndex != null; i++) {
// afterIndex = afterIndex.next;
// }
// while (afterIndex.next != null) {
// afterIndex = afterIndex.next;
// preIndex = preIndex.next;
// }
// afterIndex.next = pre.next;
// ListNode next = preIndex.next;
// preIndex.next = null;
// return next;
// }
}
class Solution2 {
public ListNode rotateRight(ListNode head, int k) {
if (head == null) {
return head;
}
ListNode pre = new ListNode(-1, head);
int len = 0;
ListNode index = pre;
while (index.next != null) {
len++;
index = index.next;
}
int add = len - k % len; // |a|k| 中的a部分
if (add == 0) {
return head;
}
index.next = pre.next;
ListNode tmp = pre;
for (int i = 0; i < add; i++) {
tmp = tmp.next;
}
ListNode cd = tmp.next;
tmp.next = null;
return cd;
}
}
}

View File

@ -0,0 +1,92 @@
package cn.whaifree.leetCode.Stack;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 15:29
* @注释
*/
public class LeetCode71 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
List<int[]> res = new ArrayList<>();
while (true) {
System.out.println("ADD");
res.add(new int[100000]);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
List<int[]> res = new ArrayList<>();
while (true) {
System.out.println(1000);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}).start();
}
@Test
public void test() {
System.out.println(new Solution().simplifyPath("/.../../.."));
}
class Solution {
/**
*
* . 当前目录
* .. 父亲目录
* ///*n /// // / 变为/
*
*
* - 碰到.. 出栈
* - 碰到. 忽略
* - N*\// 都忽略
*
*
* @param path
* @return
*/
public String simplifyPath(String path) {
Deque<String> stack = new LinkedList<>();
String[] split = path.split("/");
for (int i = 0; i < split.length; i++) {
String s = split[i];
if (s.equals("/")||s.isEmpty()||s.equals(".")) {
continue;
} else if (s.equals("..")) {
if (!stack.isEmpty()) {
stack.pop();
}
continue;
}
stack.push(s);
}
StringBuilder stringBuilder = new StringBuilder();
while (!stack.isEmpty()) {
stringBuilder.append("/");
stringBuilder.append(stack.pollLast());
}
return stringBuilder.isEmpty() ? "/" : stringBuilder.toString();
}
}
}

View File

@ -0,0 +1,92 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/23 17:31
* @注释
*/
public class LeetCode114 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{0, 1, 2, 3, 4, 5, 6});
new Solution().flatten(treeNode);
treeNode.printTree();
}
class Solution {
public void flatten(TreeNode root) {
if (root == null) {
return;
}
Deque<TreeNode> deque = new LinkedList<>();
deque.push(root);
TreeNode tmp = root;
while (!deque.isEmpty()) {
TreeNode pop = deque.pop();
if (pop != null) {
if (pop.right != null) {
deque.push(pop.right);
}
if (pop.left != null) {
deque.push(pop.left);
}
deque.push(pop);
deque.push(null);
}else {
TreeNode nextPop = deque.pop();
if (nextPop != tmp) {
tmp.right = nextPop;
tmp.left = null;
tmp = tmp.right;
}
}
}
}
}
@Test
public void test2() {
TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{0, 1, 2, 3, 4, 5, 6});
new Solution2().flatten(treeNode);
treeNode.printTree();
}
class Solution2 {
public void flatten(TreeNode root) {
if (root == null) {
return;
}
subFlatten(root);
}
public TreeNode subFlatten(TreeNode root) {
TreeNode left = root.left;
TreeNode right = root.right;
TreeNode tmp = root;
root.left = null;
if (left != null) {
root.right = left;
tmp = subFlatten(left); // tmp会返回一节的最后一个尾巴节点
}
if (right != null) {
tmp.right = right; // 把前面的right拿过来再往下
tmp = subFlatten(right);
}
return tmp;
}
}
}

View File

@ -64,7 +64,7 @@ public class ThreadDemo1 {
} }
countDownLatch.await(); countDownLatch.await(10, TimeUnit.SECONDS);
new Thread(() -> System.out.println("上面的9个执行完了,轮到我了 wait complete")).start(); new Thread(() -> System.out.println("上面的9个执行完了,轮到我了 wait complete")).start();

View File

@ -0,0 +1,211 @@
package cn.whaifree.test.io;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 20:29
* @注释
*/
public class AioServer {
public static void main(String[] args) throws IOException, InterruptedException {
// 创建一个单线程的线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 创建一个异步通道组使用线程池
AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(executorService);
// 打开一个异步服务器套接字通道并绑定到8080端口
AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open(group).bind(new InetSocketAddress(8080));
// 创建一个计数器用于等待服务器接受连接
CountDownLatch latch = new CountDownLatch(1);
// 服务器通道接受连接并指定一个完成处理器
serverChannel.accept(null, new AcceptCompletionHandler(latch));
// 等待服务器接受连接
latch.await();
// 关闭通道组
group.shutdown();
}
// 完成处理器用于处理服务器接受连接的事件
static class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Void> {
private final CountDownLatch latch;
public AcceptCompletionHandler(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void completed(AsynchronousSocketChannel result, Void attachment) {
try {
Thread.sleep(5000);
// 向客户端发送消息
result.write(ByteBuffer.wrap("Hello from server".getBytes()), null, new WriteCompletionHandler());
// 关闭客户端通道
result.close();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 计数器减一
latch.countDown();
}
@Override
public void failed(Throwable exc, Void attachment) {
// 打印异常信息
exc.printStackTrace();
}
}
// 完成处理器用于处理服务器发送消息的事件
static class WriteCompletionHandler implements CompletionHandler<Integer, Void> {
@Override
public void completed(Integer result, Void attachment) {
// 打印消息发送成功
System.out.println("Message sent");
}
@Override
public void failed(Throwable exc, Void attachment) {
// 打印异常信息
exc.printStackTrace();
}
}
}
class BioServer {
public static void main(String[] args) throws IOException {
// 创建一个服务器套接字并绑定到8080端口
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("Server started");
// 无限循环等待客户端连接
while (true) {
// 接受客户端连接
Socket socket = serverSocket.accept();
// 创建一个新的线程处理客户端连接
new Thread(new ClientHandler(socket)).start();
}
}
// 客户端处理器用于处理客户端连接
static class ClientHandler implements Runnable {
private final Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String inputLine;
// 循环读取客户端发送的消息
while ((inputLine = in.readLine()) != null) {
// 打印接收到的消息
System.out.println("Received: " + inputLine);
// 向客户端发送消息
out.println("Echo: " + inputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class NioServer {
public static void main(String[] args) throws IOException {
// 打开一个选择器
Selector selector = Selector.open();
// 打开一个服务器套接字通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 设置通道为非阻塞模式
serverSocketChannel.configureBlocking(false);
// 绑定到8080端口
serverSocketChannel.bind(new InetSocketAddress(8080));
// 注册选择器监听接受事件
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
// 无限循环等待事件发生
while (true) {
// 选择器选择准备好的通道
selector.select();
// 遍历所有准备好的通道
for (SelectionKey key : selector.selectedKeys()) {
// 如果是接受事件
if (key.isAcceptable()) {
// 处理接受事件
handleAccept(serverSocketChannel, selector);
// 如果是读取事件
} else if (key.isReadable()) {
// 处理读取事件
handleRead(key);
}
}
// 清空选择器中的事件
selector.selectedKeys().clear();
}
}
// 处理接受事件
private static void handleAccept(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException {
// 接受客户端连接
SocketChannel clientChannel = serverSocketChannel.accept();
// 设置通道为非阻塞模式
clientChannel.configureBlocking(false);
// 注册选择器监听读取事件
clientChannel.register(selector, SelectionKey.OP_READ);
}
// 处理读取事件
private static void handleRead(SelectionKey key) throws IOException {
// 获取客户端通道
SocketChannel clientChannel = (SocketChannel) key.channel();
// 创建一个缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 读取客户端发送的消息
int read = clientChannel.read(buffer);
// 如果读取到了消息
if (read > 0) {
// 将缓冲区切换到读模式
buffer.flip();
// 创建一个字节数组用于存储读取到的消息
byte[] data = new byte[read];
// 将缓冲区中的数据读取到字节数组中
buffer.get(data);
// 将字节数组转换为字符串
String message = new String(data);
// 打印接收到的消息
System.out.println("Received: " + message);
// 向客户端发送消息
clientChannel.write(ByteBuffer.wrap(("Echo: " + message).getBytes()));
}
}
}