Initial commit
This commit is contained in:
204
.gitignore
vendored
Normal file
204
.gitignore
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
### Intellij ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Intellij Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||
.idea/**/sonarlint/
|
||||
|
||||
# SonarQube Plugin
|
||||
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||
.idea/**/sonarIssues.xml
|
||||
|
||||
# Markdown Navigator plugin
|
||||
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||
.idea/**/markdown-navigator.xml
|
||||
.idea/**/markdown-navigator-enh.xml
|
||||
.idea/**/markdown-navigator/
|
||||
|
||||
# Cache file creation bug
|
||||
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||
.idea/$CACHE_FILE$
|
||||
|
||||
# CodeStream plugin
|
||||
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||
.idea/codestream.xml
|
||||
|
||||
# Azure Toolkit for IntelliJ plugin
|
||||
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
||||
.idea/**/azureSettings.xml
|
||||
|
||||
### Java ###
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
replay_pid*
|
||||
|
||||
### MicrosoftOffice ###
|
||||
*.tmp
|
||||
|
||||
# Word temporary
|
||||
~$*.doc*
|
||||
|
||||
# Word Auto Backup File
|
||||
Backup of *.doc*
|
||||
|
||||
# Excel temporary
|
||||
~$*.xls*
|
||||
|
||||
# Excel Backup File
|
||||
*.xlk
|
||||
|
||||
# PowerPoint temporary
|
||||
~$*.ppt*
|
||||
|
||||
# Visio autosave temporary files
|
||||
*.~vsd*
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
29
Classwork/.gitignore
vendored
Normal file
29
Classwork/.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
8
Classwork/.idea/.gitignore
generated
vendored
Normal file
8
Classwork/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
5
Classwork/.idea/misc.xml
generated
Normal file
5
Classwork/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
Classwork/.idea/modules.xml
generated
Normal file
8
Classwork/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Classwork.iml" filepath="$PROJECT_DIR$/Classwork.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
4
Classwork/.idea/vcs.xml
generated
Normal file
4
Classwork/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||
</project>
|
||||
11
Classwork/Classwork.iml
Normal file
11
Classwork/Classwork.iml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
40
Classwork/src/Bank/Bank.java
Normal file
40
Classwork/src/Bank/Bank.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package Bank;
|
||||
|
||||
public class Bank {
|
||||
private int money;
|
||||
private String name;
|
||||
|
||||
public Bank(String name, int money) {
|
||||
this.name = name;
|
||||
this.money = money;
|
||||
}
|
||||
|
||||
public synchronized void deposit(int m) {
|
||||
money += m;
|
||||
}
|
||||
|
||||
public synchronized boolean withdraw(int m) {
|
||||
if (money >= m) {
|
||||
money -= m;
|
||||
check();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private void check() {
|
||||
if (money < 0) {
|
||||
System.out.println("可用余额为负数,money=" + money);
|
||||
}
|
||||
/*
|
||||
else {
|
||||
System.out.println("money=" + money);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
17
Classwork/src/Bank/ClientThread.java
Normal file
17
Classwork/src/Bank/ClientThread.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package Bank;
|
||||
|
||||
public class ClientThread extends Thread{
|
||||
private Bank bank;
|
||||
public ClientThread(Bank bank) {
|
||||
this.bank = bank;
|
||||
}
|
||||
@Override
|
||||
public void run(){
|
||||
while (true){
|
||||
boolean ok=bank.withdraw(1000);
|
||||
if(ok){
|
||||
bank.deposit(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Classwork/src/Bank/MainTest.java
Normal file
15
Classwork/src/Bank/MainTest.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package Bank;
|
||||
|
||||
public class MainTest {
|
||||
public static void main(String[] args) {
|
||||
Bank bank = new Bank("a bad bank", 1000);
|
||||
new ClientThread(bank).start();
|
||||
new ClientThread(bank).start();
|
||||
new ClientThread(bank).start();
|
||||
new ClientThread(bank).start();
|
||||
new ClientThread(bank).start();
|
||||
new ClientThread(bank).start();
|
||||
new ClientThread(bank).start();
|
||||
new ClientThread(bank).start();
|
||||
}
|
||||
}
|
||||
45
Classwork/src/Buffer/BufferCreateIO.java
Normal file
45
Classwork/src/Buffer/BufferCreateIO.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package Buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static Buffer.BufferOperation.bufferToString;
|
||||
|
||||
public class BufferCreateIO {
|
||||
public static void main(String[] args) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(10);
|
||||
System.out.println("初始状态: " + bufferToString(buffer));
|
||||
|
||||
// 向缓冲区依次写入字节 1, 2, 3, 4, 5
|
||||
buffer.put((byte) 1);
|
||||
buffer.put((byte) 2);
|
||||
buffer.put((byte) 3);
|
||||
buffer.put((byte) 4);
|
||||
buffer.put((byte) 5);
|
||||
System.out.println("写入5个字节后: " + bufferToString(buffer));
|
||||
|
||||
// 切换为读模式
|
||||
buffer.flip();
|
||||
System.out.println("调用flip()后 (读模式): " + bufferToString(buffer));
|
||||
|
||||
// 读取并打印所有数据
|
||||
System.out.print("读取数据: ");
|
||||
while (buffer.hasRemaining()) {
|
||||
System.out.print(buffer.get() + " ");
|
||||
}
|
||||
System.out.println("\n读取完毕后: " + bufferToString(buffer));
|
||||
|
||||
// 清空缓冲区
|
||||
buffer.clear();
|
||||
System.out.println("调用clear()后: " + bufferToString(buffer));
|
||||
|
||||
// 验证是否可重新写入
|
||||
buffer.put((byte) 6);
|
||||
System.out.println("重新写入一个字节 (6) 后: " + bufferToString(buffer));
|
||||
buffer.flip();
|
||||
System.out.print("读取新写入的数据: ");
|
||||
while (buffer.hasRemaining()) {
|
||||
System.out.print(buffer.get() + " ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
24
Classwork/src/Buffer/BufferOperation.java
Normal file
24
Classwork/src/Buffer/BufferOperation.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package Buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
public class BufferOperation {
|
||||
public static String bufferToString(ByteBuffer buffer) {
|
||||
return "pos=" + buffer.position() + " lim=" + buffer.limit() + " cap=" + buffer.capacity();
|
||||
}
|
||||
public static String charBufferToString(CharBuffer buffer) {
|
||||
return "pos=" + buffer.position() + " lim=" + buffer.limit() + " cap=" + buffer.capacity();
|
||||
}
|
||||
public static String intBufferToString(IntBuffer buffer) {
|
||||
return "pos=" + buffer.position() + " lim=" + buffer.limit() + " cap=" + buffer.capacity();
|
||||
}
|
||||
public static String bytesToHex(byte[] bytes, int length) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(String.format("%02X ", bytes[i]));
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
}
|
||||
56
Classwork/src/Data/Data.java
Normal file
56
Classwork/src/Data/Data.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package Data;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class Data {
|
||||
private final char[] buffer;
|
||||
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
|
||||
private final Lock readLock = rwLock.readLock();
|
||||
private final Lock writeLock = rwLock.writeLock();
|
||||
|
||||
public Data(int size) {
|
||||
this.buffer = new char[size];
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
buffer[i] = '*';
|
||||
}
|
||||
}
|
||||
|
||||
public char[] read() throws InterruptedException {
|
||||
readLock.lock();
|
||||
try {
|
||||
return doRead();
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void write(char c) throws InterruptedException {
|
||||
writeLock.lock();
|
||||
try {
|
||||
doWrite(c);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private char[] doRead() throws InterruptedException {
|
||||
char[] newbuf = new char[buffer.length];
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
newbuf[i] = buffer[i];
|
||||
}
|
||||
slowly();
|
||||
return newbuf;
|
||||
}
|
||||
|
||||
private void doWrite(char c) throws InterruptedException {
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
buffer[i] = c;
|
||||
slowly();
|
||||
}
|
||||
}
|
||||
|
||||
private void slowly() throws InterruptedException {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
}
|
||||
40
Classwork/src/Data/Main.java
Normal file
40
Classwork/src/Data/Main.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package Data;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Data data = new Data(10);
|
||||
|
||||
ReaderThread reader1 = new ReaderThread("Reader-1", data);
|
||||
ReaderThread reader2 = new ReaderThread("Reader-2", data);
|
||||
ReaderThread reader3 = new ReaderThread("Reader-3", data);
|
||||
ReaderThread reader4 = new ReaderThread("Reader-4", data);
|
||||
|
||||
WriterThread writer1 = new WriterThread("Writer-A", data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
WriterThread writer2 = new WriterThread("Writer-B", data, "abcdefghijklmnopqrstuvwxyz");
|
||||
|
||||
System.out.println("Starting threads...");
|
||||
|
||||
reader1.start();
|
||||
reader2.start();
|
||||
writer1.start();
|
||||
reader3.start();
|
||||
reader4.start();
|
||||
writer2.start();
|
||||
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
System.out.println("\nInterrupting threads...");
|
||||
reader1.interrupt();
|
||||
reader2.interrupt();
|
||||
reader3.interrupt();
|
||||
reader4.interrupt();
|
||||
writer1.interrupt();
|
||||
writer2.interrupt();
|
||||
|
||||
System.out.println("Main thread finished.");
|
||||
}
|
||||
}
|
||||
24
Classwork/src/Data/ReaderThread.java
Normal file
24
Classwork/src/Data/ReaderThread.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package Data;
|
||||
|
||||
public class ReaderThread extends Thread {
|
||||
private final Data data;
|
||||
|
||||
public ReaderThread(String name, Data data) {
|
||||
super(name);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
char[] readBuf = data.read();
|
||||
System.out.println(Thread.currentThread().getName() + " reads " + String.valueOf(readBuf));
|
||||
Thread.sleep(100);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(Thread.currentThread().getName() + " was interrupted.");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Classwork/src/Data/WriterThread.java
Normal file
37
Classwork/src/Data/WriterThread.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package Data;
|
||||
|
||||
public class WriterThread extends Thread {
|
||||
private final Data data;
|
||||
private final String filler;
|
||||
private int index = 0;
|
||||
|
||||
public WriterThread(String name, Data data, String filler) {
|
||||
super(name);
|
||||
this.data = data;
|
||||
this.filler = filler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
char c = nextChar();
|
||||
data.write(c);
|
||||
System.out.println(Thread.currentThread().getName() + " writes " + c);
|
||||
Thread.sleep(300);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(Thread.currentThread().getName() + " was interrupted.");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private char nextChar() {
|
||||
char c = filler.charAt(index);
|
||||
index++;
|
||||
if (index >= filler.length()) {
|
||||
index = 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
63
Classwork/src/DataLimited/Data.java
Normal file
63
Classwork/src/DataLimited/Data.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package DataLimited;
|
||||
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class Data {
|
||||
private final char[] buffer;
|
||||
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
|
||||
private final Lock readLock = rwLock.readLock();
|
||||
private final Lock writeLock = rwLock.writeLock();
|
||||
private final Semaphore readSemaphore = new Semaphore(3);
|
||||
|
||||
public Data(int size) {
|
||||
this.buffer = new char[size];
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
buffer[i] = '*';
|
||||
}
|
||||
}
|
||||
|
||||
public char[] read() throws InterruptedException {
|
||||
readSemaphore.acquire();
|
||||
try {
|
||||
readLock.lock();
|
||||
try {
|
||||
return doRead();
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readSemaphore.release();
|
||||
}
|
||||
}
|
||||
|
||||
public void write(char c) throws InterruptedException {
|
||||
writeLock.lock();
|
||||
try {
|
||||
doWrite(c);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private char[] doRead() throws InterruptedException {
|
||||
char[] newbuf = new char[buffer.length];
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
newbuf[i] = buffer[i];
|
||||
}
|
||||
slowly();
|
||||
return newbuf;
|
||||
}
|
||||
|
||||
private void doWrite(char c) throws InterruptedException {
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
buffer[i] = c;
|
||||
slowly();
|
||||
}
|
||||
}
|
||||
|
||||
private void slowly() throws InterruptedException {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
}
|
||||
40
Classwork/src/DataLimited/Main.java
Normal file
40
Classwork/src/DataLimited/Main.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package DataLimited;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Data data = new Data(10);
|
||||
|
||||
ReaderThread reader1 = new ReaderThread("Reader-1", data);
|
||||
ReaderThread reader2 = new ReaderThread("Reader-2", data);
|
||||
ReaderThread reader3 = new ReaderThread("Reader-3", data);
|
||||
ReaderThread reader4 = new ReaderThread("Reader-4", data);
|
||||
|
||||
WriterThread writer1 = new WriterThread("Writer-A", data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
WriterThread writer2 = new WriterThread("Writer-B", data, "abcdefghijklmnopqrstuvwxyz");
|
||||
|
||||
System.out.println("Starting threads...");
|
||||
|
||||
reader1.start();
|
||||
reader2.start();
|
||||
writer1.start();
|
||||
reader3.start();
|
||||
reader4.start();
|
||||
writer2.start();
|
||||
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
System.out.println("\nInterrupting threads...");
|
||||
reader1.interrupt();
|
||||
reader2.interrupt();
|
||||
reader3.interrupt();
|
||||
reader4.interrupt();
|
||||
writer1.interrupt();
|
||||
writer2.interrupt();
|
||||
|
||||
System.out.println("Main thread finished.");
|
||||
}
|
||||
}
|
||||
24
Classwork/src/DataLimited/ReaderThread.java
Normal file
24
Classwork/src/DataLimited/ReaderThread.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package DataLimited;
|
||||
|
||||
public class ReaderThread extends Thread {
|
||||
private final Data data;
|
||||
|
||||
public ReaderThread(String name, Data data) {
|
||||
super(name);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
char[] readBuf = data.read();
|
||||
System.out.println(Thread.currentThread().getName() + " reads " + String.valueOf(readBuf));
|
||||
Thread.sleep(100);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(Thread.currentThread().getName() + " was interrupted.");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Classwork/src/DataLimited/WriterThread.java
Normal file
37
Classwork/src/DataLimited/WriterThread.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package DataLimited;
|
||||
|
||||
public class WriterThread extends Thread {
|
||||
private final Data data;
|
||||
private final String filler;
|
||||
private int index = 0;
|
||||
|
||||
public WriterThread(String name, Data data, String filler) {
|
||||
super(name);
|
||||
this.data = data;
|
||||
this.filler = filler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
char c = nextChar();
|
||||
data.write(c);
|
||||
System.out.println(Thread.currentThread().getName() + " writes " + c);
|
||||
Thread.sleep(300);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(Thread.currentThread().getName() + " was interrupted.");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private char nextChar() {
|
||||
char c = filler.charAt(index);
|
||||
index++;
|
||||
if (index >= filler.length()) {
|
||||
index = 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
19
Classwork/src/ProducerConsumer/extthread/ThreadC.java
Normal file
19
Classwork/src/ProducerConsumer/extthread/ThreadC.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package ProducerConsumer.extthread;
|
||||
|
||||
import ProducerConsumer.service.RepastService;
|
||||
|
||||
public class ThreadC extends Thread {
|
||||
|
||||
private RepastService service;
|
||||
|
||||
public ThreadC(RepastService service) {
|
||||
super();
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
service.get();
|
||||
}
|
||||
|
||||
}
|
||||
19
Classwork/src/ProducerConsumer/extthread/ThreadP.java
Normal file
19
Classwork/src/ProducerConsumer/extthread/ThreadP.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package ProducerConsumer.extthread;
|
||||
|
||||
import ProducerConsumer.service.RepastService;
|
||||
|
||||
public class ThreadP extends Thread {
|
||||
|
||||
private RepastService service;
|
||||
|
||||
public ThreadP(RepastService service) {
|
||||
super();
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
service.set();
|
||||
}
|
||||
|
||||
}
|
||||
94
Classwork/src/ProducerConsumer/service/RepastService.java
Normal file
94
Classwork/src/ProducerConsumer/service/RepastService.java
Normal file
@@ -0,0 +1,94 @@
|
||||
package ProducerConsumer.service;
|
||||
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class RepastService {
|
||||
|
||||
volatile private Semaphore setSemaphore = new Semaphore(10);// 厨师
|
||||
volatile private Semaphore getSemaphore = new Semaphore(20);// 就餐者
|
||||
volatile private ReentrantLock lock = new ReentrantLock();
|
||||
volatile private Condition setCondition = lock.newCondition();
|
||||
volatile private Condition getCondition = lock.newCondition();
|
||||
volatile private Object[] producePosition = new Object[4];
|
||||
|
||||
private boolean isEmpty() {
|
||||
boolean isEmpty = true;
|
||||
for (int i = 0; i < producePosition.length; i++) {
|
||||
if (producePosition[i] != null) {
|
||||
isEmpty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isEmpty == true) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFull() {
|
||||
boolean isFull = true;
|
||||
for (int i = 0; i < producePosition.length; i++) {
|
||||
if (producePosition[i] == null) {
|
||||
isFull = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isFull;
|
||||
}
|
||||
|
||||
public void set() {
|
||||
try {
|
||||
// System.out.println("set");
|
||||
setSemaphore.acquire();// 允许同时最多有10个厨师进行生产
|
||||
lock.lock();
|
||||
while (isFull()) {
|
||||
System.out.println("生产者在等待");
|
||||
setCondition.await();
|
||||
}
|
||||
for (int i = 0; i < producePosition.length; i++) {
|
||||
if (producePosition[i] == null) {
|
||||
producePosition[i] = "数据";
|
||||
System.out.println(Thread.currentThread().getName()
|
||||
+ " 生产了 " + producePosition[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
getCondition.signalAll();
|
||||
lock.unlock();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
setSemaphore.release();
|
||||
}
|
||||
}
|
||||
|
||||
public void get() {
|
||||
try {
|
||||
// System.out.println("get");
|
||||
getSemaphore.acquire();// 允许同时最多有16个就餐者
|
||||
lock.lock();
|
||||
while (isEmpty()) {
|
||||
System.out.println("消费者在等待");
|
||||
getCondition.await();
|
||||
}
|
||||
for (int i = 0; i < producePosition.length; i++) {
|
||||
if (producePosition[i] != null) {
|
||||
System.out.println(Thread.currentThread().getName()
|
||||
+ " 消费了 " + producePosition[i]);
|
||||
producePosition[i] = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setCondition.signalAll();
|
||||
lock.unlock();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
getSemaphore.release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
24
Classwork/src/ProducerConsumer/test/run/Run.java
Normal file
24
Classwork/src/ProducerConsumer/test/run/Run.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package ProducerConsumer.test.run;
|
||||
|
||||
import ProducerConsumer.service.RepastService;
|
||||
import ProducerConsumer.extthread.ThreadC;
|
||||
import ProducerConsumer.extthread.ThreadP;
|
||||
|
||||
public class Run {
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
RepastService service = new RepastService();
|
||||
ThreadP[] arrayP = new ThreadP[60];
|
||||
ThreadC[] arrayC = new ThreadC[60];
|
||||
for (int i = 0; i < 60; i++) {
|
||||
arrayP[i] = new ThreadP(service);
|
||||
arrayC[i] = new ThreadC(service);
|
||||
}
|
||||
Thread.sleep(2000);
|
||||
for (int i = 0; i < 60; i++) {
|
||||
arrayP[i].start();
|
||||
arrayC[i].start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
88
Classwork/src/Race/TortoiseHareRace.java
Normal file
88
Classwork/src/Race/TortoiseHareRace.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package Race;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TortoiseHareRace {
|
||||
private static final int RACE_LENGTH = 100; // 赛道长度(米)
|
||||
private static int tortoisePosition = 0; // 乌龟位置
|
||||
private static int harePosition = 0; // 兔子位置
|
||||
private static boolean raceFinished = false; // 比赛是否结束
|
||||
private static final Object lock = new Object(); // 同步锁
|
||||
|
||||
public static void main(String[] args) {
|
||||
Random random = new Random();
|
||||
|
||||
// 乌龟线程:速度慢但稳定
|
||||
Thread tortoise = new Thread(() -> {
|
||||
while (!raceFinished) {
|
||||
synchronized (lock) {
|
||||
// 乌龟每次移动1-2米
|
||||
int step = random.nextInt(2) + 1;
|
||||
tortoisePosition += step;
|
||||
System.out.println("乌龟前进了" + step + "米,当前位置:" + tortoisePosition + "米");
|
||||
|
||||
if (tortoisePosition >= RACE_LENGTH) {
|
||||
raceFinished = true;
|
||||
System.out.println("乌龟赢得了比赛!");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(200);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, "乌龟");
|
||||
|
||||
// 兔子线程:速度快但会休息
|
||||
Thread hare = new Thread(() -> {
|
||||
while (!raceFinished) {
|
||||
synchronized (lock) {
|
||||
// 兔子移动速度更快,每次移动5-10米
|
||||
int step = random.nextInt(6) + 5;
|
||||
harePosition += step;
|
||||
System.out.println("兔子前进了" + step + "米,当前位置:" + harePosition + "米");
|
||||
|
||||
if (harePosition >= RACE_LENGTH) {
|
||||
raceFinished = true;
|
||||
System.out.println("兔子赢得了比赛!");
|
||||
}
|
||||
}
|
||||
|
||||
// 兔子有30%的概率会休息
|
||||
if (random.nextInt(10) < 3) {
|
||||
int restTime = random.nextInt(600) + 200;
|
||||
System.out.println("兔子太自信了,休息" + restTime + "毫秒");
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(restTime);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, "兔子");
|
||||
|
||||
System.out.println("比赛开始!");
|
||||
tortoise.start();
|
||||
hare.start();
|
||||
|
||||
try {
|
||||
tortoise.join();
|
||||
hare.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("比赛结束!");
|
||||
System.out.println("最终结果 - 乌龟:" + Math.min(tortoisePosition, RACE_LENGTH) +
|
||||
"米,兔子:" + Math.min(harePosition, RACE_LENGTH) + "米");
|
||||
}
|
||||
}
|
||||
78
Classwork/src/RedPacket/AICRedPacketGrabber.java
Normal file
78
Classwork/src/RedPacket/AICRedPacketGrabber.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package RedPacket;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class AICRedPacketGrabber {
|
||||
private static int totalMoney = 100;
|
||||
private static int thread1Money = 0;
|
||||
private static int thread2Money = 0;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
public static void main(String[] args) {
|
||||
Thread thread1 = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
grabMoney(true);
|
||||
}
|
||||
}, "线程1");
|
||||
|
||||
Thread thread2 = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
grabMoney(false);
|
||||
}
|
||||
}, "线程2");
|
||||
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
|
||||
try {
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("线程1抢到的总金额: " + thread1Money + "元");
|
||||
System.out.println("线程2抢到的总金额: " + thread2Money + "元");
|
||||
System.out.println("剩余金额: " + totalMoney + "元");
|
||||
}
|
||||
|
||||
private static void grabMoney(boolean isThread1) {
|
||||
Random random = new Random();
|
||||
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
if (totalMoney < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
int grabMoney = random.nextInt(3) + 1;
|
||||
|
||||
if (grabMoney > totalMoney) {
|
||||
grabMoney = totalMoney;
|
||||
}
|
||||
|
||||
totalMoney -= grabMoney;
|
||||
|
||||
if (isThread1) {
|
||||
thread1Money += grabMoney;
|
||||
System.out.println("线程1抢到了" + grabMoney + "元,剩余" + totalMoney + "元");
|
||||
} else {
|
||||
thread2Money += grabMoney;
|
||||
System.out.println("线程2抢到了" + grabMoney + "元,剩余" + totalMoney + "元");
|
||||
}
|
||||
|
||||
if (totalMoney == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Classwork/src/RedPacket/CFRedPacketGrabber.java
Normal file
91
Classwork/src/RedPacket/CFRedPacketGrabber.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package RedPacket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class CFRedPacketGrabber {
|
||||
private static int totalMoney = 100;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.print("请输入参与抢红包的线程数: ");
|
||||
int threadCount = scanner.nextInt();
|
||||
scanner.close();
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
||||
List<Future<Integer>> futures = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
final int threadId = i + 1;
|
||||
Future<Integer> future = executor.submit(new RedPacketGrabber(threadId));
|
||||
futures.add(future);
|
||||
}
|
||||
|
||||
int[] threadMoney = new int[threadCount];
|
||||
try {
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
threadMoney[i] = futures.get(i).get();
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
System.out.println("线程" + (i + 1) + "抢到的总金额: " + threadMoney[i] + "元");
|
||||
}
|
||||
System.out.println("剩余金额: " + totalMoney + "元");
|
||||
}
|
||||
|
||||
static class RedPacketGrabber implements Callable<Integer> {
|
||||
private final int threadId;
|
||||
private int moneyGrabbed = 0;
|
||||
|
||||
public RedPacketGrabber(int threadId) {
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer call() {
|
||||
Random random = new Random();
|
||||
String threadName = "线程" + threadId;
|
||||
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
if (totalMoney < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
int grabMoney = random.nextInt(3) + 1;
|
||||
|
||||
if (grabMoney > totalMoney) {
|
||||
grabMoney = totalMoney;
|
||||
}
|
||||
|
||||
totalMoney -= grabMoney;
|
||||
moneyGrabbed += grabMoney;
|
||||
|
||||
System.out.println(threadName + "抢到了" + grabMoney + "元,剩余" + totalMoney + "元");
|
||||
|
||||
if (totalMoney == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return moneyGrabbed;
|
||||
}
|
||||
}
|
||||
}
|
||||
82
Classwork/src/RedPacket/LambdaRedPacketGrabber.java
Normal file
82
Classwork/src/RedPacket/LambdaRedPacketGrabber.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package RedPacket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class LambdaRedPacketGrabber {
|
||||
private static int totalMoney = 100;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.print("请输入参与抢红包的线程数: ");
|
||||
int threadCount = scanner.nextInt();
|
||||
scanner.close();
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
||||
List<Future<Integer>> futures = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
final int threadId = i + 1;
|
||||
|
||||
Future<Integer> future = executor.submit(() -> {
|
||||
Random random = new Random();
|
||||
String threadName = "线程" + threadId;
|
||||
int moneyGrabbed = 0;
|
||||
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
if (totalMoney < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
int grabMoney = random.nextInt(3) + 1;
|
||||
|
||||
if (grabMoney > totalMoney) {
|
||||
grabMoney = totalMoney;
|
||||
}
|
||||
|
||||
totalMoney -= grabMoney;
|
||||
moneyGrabbed += grabMoney;
|
||||
|
||||
System.out.println(threadName + "抢到了" + grabMoney + "元,剩余" + totalMoney + "元");
|
||||
|
||||
if (totalMoney == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return moneyGrabbed;
|
||||
});
|
||||
|
||||
futures.add(future);
|
||||
}
|
||||
|
||||
int[] threadMoney = new int[threadCount];
|
||||
try {
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
threadMoney[i] = futures.get(i).get();
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
System.out.println("线程" + (i + 1) + "抢到的总金额: " + threadMoney[i] + "元");
|
||||
}
|
||||
System.out.println("剩余金额: " + totalMoney + "元");
|
||||
}
|
||||
}
|
||||
76
Classwork/src/RedPacket/OrderedRedPacketGrabber.java
Normal file
76
Classwork/src/RedPacket/OrderedRedPacketGrabber.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package RedPacket;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class OrderedRedPacketGrabber {
|
||||
private static int totalMoney = 100;
|
||||
private static int thread1Money = 0;
|
||||
private static int thread2Money = 0;
|
||||
private static boolean isThread1Turn = true;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
public static void main(String[] args) {
|
||||
Thread thread1 = new Thread(() -> grabMoney(true), "线程1");
|
||||
Thread thread2 = new Thread(() -> grabMoney(false), "线程2");
|
||||
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
|
||||
try {
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("线程1抢到的总金额: " + thread1Money + "元");
|
||||
System.out.println("线程2抢到的总金额: " + thread2Money + "元");
|
||||
System.out.println("剩余金额: " + totalMoney + "元");
|
||||
}
|
||||
|
||||
private static void grabMoney(boolean isThread1) {
|
||||
Random random = new Random();
|
||||
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
while (isThread1Turn != isThread1 && totalMoney >= 1) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (totalMoney < 1) {
|
||||
lock.notifyAll();
|
||||
break;
|
||||
}
|
||||
|
||||
int grabMoney = random.nextInt(3) + 1;
|
||||
|
||||
if (grabMoney > totalMoney) {
|
||||
grabMoney = totalMoney;
|
||||
}
|
||||
|
||||
totalMoney -= grabMoney;
|
||||
|
||||
if (isThread1) {
|
||||
thread1Money += grabMoney;
|
||||
System.out.println("线程1抢到了" + grabMoney + "元,剩余" + totalMoney + "元");
|
||||
} else {
|
||||
thread2Money += grabMoney;
|
||||
System.out.println("线程2抢到了" + grabMoney + "元,剩余" + totalMoney + "元");
|
||||
}
|
||||
|
||||
isThread1Turn = !isThread1Turn;
|
||||
|
||||
lock.notify();
|
||||
|
||||
if (totalMoney == 0) {
|
||||
lock.notifyAll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
Classwork/src/RedPacket/RandomRedPacketGrabber.java
Normal file
67
Classwork/src/RedPacket/RandomRedPacketGrabber.java
Normal file
@@ -0,0 +1,67 @@
|
||||
package RedPacket;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomRedPacketGrabber {
|
||||
private static int totalMoney = 100;
|
||||
private static int thread1Money = 0;
|
||||
private static int thread2Money = 0;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
public static void main(String[] args) {
|
||||
Thread thread1 = new Thread(() -> grabMoney(true), "线程1");
|
||||
Thread thread2 = new Thread(() -> grabMoney(false), "线程2");
|
||||
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
|
||||
try {
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("线程1抢到的总金额: " + thread1Money + "元");
|
||||
System.out.println("线程2抢到的总金额: " + thread2Money + "元");
|
||||
System.out.println("剩余金额: " + totalMoney + "元");
|
||||
}
|
||||
|
||||
private static void grabMoney(boolean isThread1) {
|
||||
Random random = new Random();
|
||||
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
if (totalMoney < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
int grabMoney = random.nextInt(3) + 1;
|
||||
|
||||
if (grabMoney > totalMoney) {
|
||||
grabMoney = totalMoney;
|
||||
}
|
||||
|
||||
totalMoney -= grabMoney;
|
||||
|
||||
if (isThread1) {
|
||||
thread1Money += grabMoney;
|
||||
System.out.println("线程1抢到了" + grabMoney + "元,剩余" + totalMoney + "元");
|
||||
} else {
|
||||
thread2Money += grabMoney;
|
||||
System.out.println("线程2抢到了" + grabMoney + "元,剩余" + totalMoney + "元");
|
||||
}
|
||||
|
||||
if (totalMoney == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Classwork/src/RedPacket/ThreadPoolRedPacketGrabber.java
Normal file
88
Classwork/src/RedPacket/ThreadPoolRedPacketGrabber.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package RedPacket;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class ThreadPoolRedPacketGrabber {
|
||||
private static int totalMoney = 100;
|
||||
private static final int THREAD_COUNT = 2;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
public static void main(String[] args) {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
|
||||
|
||||
int[] threadMoney = new int[THREAD_COUNT];
|
||||
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
final int threadId = i;
|
||||
executor.submit(new RedPacketGrabber(threadId, threadMoney, latch));
|
||||
}
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
System.out.println("线程" + (i + 1) + "抢到的总金额: " + threadMoney[i] + "元");
|
||||
}
|
||||
System.out.println("剩余金额: " + totalMoney + "元");
|
||||
}
|
||||
|
||||
static class RedPacketGrabber implements Runnable {
|
||||
private final int threadId;
|
||||
private final int[] threadMoney;
|
||||
private final CountDownLatch latch;
|
||||
|
||||
public RedPacketGrabber(int threadId, int[] threadMoney, CountDownLatch latch) {
|
||||
this.threadId = threadId;
|
||||
this.threadMoney = threadMoney;
|
||||
this.latch = latch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Random random = new Random();
|
||||
String threadName = "线程" + (threadId + 1);
|
||||
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
if (totalMoney < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
int grabMoney = random.nextInt(3) + 1;
|
||||
|
||||
if (grabMoney > totalMoney) {
|
||||
grabMoney = totalMoney;
|
||||
}
|
||||
|
||||
totalMoney -= grabMoney;
|
||||
threadMoney[threadId] += grabMoney;
|
||||
|
||||
System.out.println(threadName + "抢到了" + grabMoney + "元,剩余" + totalMoney + "元");
|
||||
|
||||
if (totalMoney == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Final/.gitignore
vendored
Normal file
29
Final/.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
10
Final/.idea/.gitignore
generated
vendored
Normal file
10
Final/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# 依赖于环境的 Maven 主目录路径
|
||||
/mavenHomeManager.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
6
Final/.idea/misc.xml
generated
Normal file
6
Final/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
Final/.idea/modules.xml
generated
Normal file
8
Final/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Final.iml" filepath="$PROJECT_DIR$/Final.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
124
Final/.idea/uiDesigner.xml
generated
Normal file
124
Final/.idea/uiDesigner.xml
generated
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
4
Final/.idea/vcs.xml
generated
Normal file
4
Final/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||
</project>
|
||||
11
Final/Final.iml
Normal file
11
Final/Final.iml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
108
Final/src/aio/AIOChatClient.java
Normal file
108
Final/src/aio/AIOChatClient.java
Normal file
@@ -0,0 +1,108 @@
|
||||
package aio;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.AsynchronousSocketChannel;
|
||||
import java.nio.channels.CompletionHandler;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class AIOChatClient {
|
||||
private static final String HOST = "127.0.0.1";
|
||||
private static final int PORT = 8888;
|
||||
private AsynchronousSocketChannel clientChannel;
|
||||
private CountDownLatch latch;
|
||||
public void start() throws Exception {
|
||||
clientChannel = AsynchronousSocketChannel.open();
|
||||
latch = new CountDownLatch(1);
|
||||
clientChannel.connect(new InetSocketAddress(HOST, PORT), null, new CompletionHandler<Void, Object>() {
|
||||
@Override
|
||||
public void completed(Void result, Object attachment) {
|
||||
System.out.println("成功连接到服务器。现在可以开始聊天了(输入 'exit' 退出)。");
|
||||
startRead();
|
||||
startWrite();
|
||||
}
|
||||
@Override
|
||||
public void failed(Throwable exc, Object attachment) {
|
||||
System.err.println("连接服务器失败: " + exc.getMessage());
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
latch.await();
|
||||
}
|
||||
private void startRead() {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
clientChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
|
||||
@Override
|
||||
public void completed(Integer result, ByteBuffer attachment) {
|
||||
if (result > 0) {
|
||||
attachment.flip();
|
||||
String message = StandardCharsets.UTF_8.decode(attachment).toString();
|
||||
System.out.println(message);
|
||||
attachment.clear();
|
||||
} else if (result == -1) {
|
||||
handleDisconnect();
|
||||
return;
|
||||
}
|
||||
if (clientChannel.isOpen()) {
|
||||
clientChannel.read(attachment, attachment, this);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void failed(Throwable exc, ByteBuffer attachment) {
|
||||
System.err.println("读取数据失败: " + exc.getMessage());
|
||||
handleDisconnect();
|
||||
}
|
||||
});
|
||||
}
|
||||
private void startWrite() {
|
||||
new Thread(() -> {
|
||||
BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
|
||||
try {
|
||||
String message;
|
||||
while ((message = consoleReader.readLine()) != null) {
|
||||
if ("exit".equalsIgnoreCase(message.trim())) {
|
||||
break;
|
||||
}
|
||||
ByteBuffer buffer = StandardCharsets.UTF_8.encode(message);
|
||||
clientChannel.write(buffer, null, new CompletionHandler<Integer, Object>() {
|
||||
@Override
|
||||
public void completed(Integer result, Object attachment) {}
|
||||
@Override
|
||||
public void failed(Throwable exc, Object attachment) {
|
||||
System.err.println("发送消息失败: " + exc.getMessage());
|
||||
handleDisconnect();
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
handleDisconnect();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
private void handleDisconnect() {
|
||||
try {
|
||||
if (clientChannel.isOpen()) {
|
||||
clientChannel.close();
|
||||
System.out.println("与服务器的连接已断开。");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
new AIOChatClient().start();
|
||||
} catch (Exception e) {
|
||||
System.err.println("客户端启动时发生错误。");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
127
Final/src/aio/AIOChatServer.java
Normal file
127
Final/src/aio/AIOChatServer.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package aio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.AsynchronousChannelGroup;
|
||||
import java.nio.channels.AsynchronousServerSocketChannel;
|
||||
import java.nio.channels.AsynchronousSocketChannel;
|
||||
import java.nio.channels.CompletionHandler;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class AIOChatServer {
|
||||
private static final int PORT = 8888;
|
||||
private AsynchronousServerSocketChannel serverSocketChannel;
|
||||
private final CopyOnWriteArrayList<AsynchronousSocketChannel> clients = new CopyOnWriteArrayList<>();
|
||||
public void start() {
|
||||
try {
|
||||
AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(Executors.newFixedThreadPool(10));
|
||||
serverSocketChannel = AsynchronousServerSocketChannel.open(group);
|
||||
serverSocketChannel.bind(new InetSocketAddress(PORT));
|
||||
System.out.println("服务器已启动,监听端口:" + PORT);
|
||||
serverSocketChannel.accept(null, new AcceptHandler());
|
||||
System.in.read();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
private class AcceptHandler implements CompletionHandler<AsynchronousSocketChannel, Object> {
|
||||
@Override
|
||||
public void completed(AsynchronousSocketChannel clientChannel, Object attachment) {
|
||||
serverSocketChannel.accept(null, this);
|
||||
clients.add(clientChannel);
|
||||
try {
|
||||
System.out.println("客户端 [" + clientChannel.getRemoteAddress() + "] 已连接。当前在线人数:" + clients.size());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
clientChannel.read(buffer, new ClientSession(clientChannel, buffer), new ReadWriteHandler());
|
||||
}
|
||||
@Override
|
||||
public void failed(Throwable exc, Object attachment) {
|
||||
System.out.println("接受连接失败:" + exc);
|
||||
}
|
||||
}
|
||||
private class ReadWriteHandler implements CompletionHandler<Integer, ClientSession> {
|
||||
@Override
|
||||
public void completed(Integer result, ClientSession session) {
|
||||
if (result > 0) {
|
||||
session.buffer.flip();
|
||||
String receivedMessage = StandardCharsets.UTF_8.decode(session.buffer).toString().trim();
|
||||
if (!receivedMessage.isEmpty()) {
|
||||
String messageToSend;
|
||||
try {
|
||||
messageToSend = "客户端 [" + session.clientChannel.getRemoteAddress() + "] 说: " + receivedMessage;
|
||||
System.out.println("正在广播: " + messageToSend);
|
||||
broadcast(messageToSend, session.clientChannel);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
session.buffer.clear();
|
||||
session.clientChannel.read(session.buffer, session, this);
|
||||
} else if (result == -1) {
|
||||
handleDisconnect(session.clientChannel);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void failed(Throwable exc, ClientSession session) {
|
||||
System.out.println("读写数据时发生错误:" + exc.getMessage());
|
||||
handleDisconnect(session.clientChannel);
|
||||
}
|
||||
}
|
||||
private void broadcast(String message, AsynchronousSocketChannel sender) {
|
||||
ByteBuffer initialBuffer = StandardCharsets.UTF_8.encode(message);
|
||||
for (AsynchronousSocketChannel client : clients) {
|
||||
if (client.isOpen() && !client.equals(sender)) {
|
||||
ByteBuffer bufferForWriting = initialBuffer.duplicate();
|
||||
class WriteContext {
|
||||
final AsynchronousSocketChannel clientChannel;
|
||||
final ByteBuffer buffer;
|
||||
WriteContext(AsynchronousSocketChannel client, ByteBuffer buf) {
|
||||
this.clientChannel = client;
|
||||
this.buffer = buf;
|
||||
}
|
||||
}
|
||||
WriteContext context = new WriteContext(client, bufferForWriting);
|
||||
client.write(bufferForWriting, context, new CompletionHandler<Integer, WriteContext>() {
|
||||
@Override
|
||||
public void completed(Integer result, WriteContext attachment) {
|
||||
// 如果缓冲区中还有剩余数据,说明是一次“部分写”,需要继续发送
|
||||
if (attachment.buffer.hasRemaining()) {
|
||||
attachment.clientChannel.write(attachment.buffer, attachment, this);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void failed(Throwable exc, WriteContext attachment) {
|
||||
System.err.println("向客户端 " + attachment.clientChannel + " 广播消息失败: " + exc);
|
||||
handleDisconnect(attachment.clientChannel);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
private void handleDisconnect(AsynchronousSocketChannel clientChannel) {
|
||||
clients.remove(clientChannel);
|
||||
try {
|
||||
System.out.println("客户端 [" + clientChannel.getRemoteAddress() + "] 已断开连接。当前在线人数:" + clients.size());
|
||||
clientChannel.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClientSession {
|
||||
AsynchronousSocketChannel clientChannel;
|
||||
ByteBuffer buffer;
|
||||
public ClientSession(AsynchronousSocketChannel clientChannel, ByteBuffer buffer) {
|
||||
this.clientChannel = clientChannel;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
new AIOChatServer().start();
|
||||
}
|
||||
}
|
||||
96
Final/src/aio/AsyncQueueDemo.java
Normal file
96
Final/src/aio/AsyncQueueDemo.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package aio;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class AsyncQueueDemo {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
final int QUEUE_CAPACITY = 10;
|
||||
final int PRODUCER_COUNT = 3;
|
||||
final int CONSUMER_COUNT = 5;
|
||||
final int ITEMS_PER_PRODUCER = 20;
|
||||
AsyncQueue<String> queue = new AsyncQueue<>(QUEUE_CAPACITY);
|
||||
ExecutorService producerExecutor = Executors.newFixedThreadPool(PRODUCER_COUNT);
|
||||
ExecutorService consumerExecutor = Executors.newFixedThreadPool(CONSUMER_COUNT);
|
||||
AtomicInteger producedCount = new AtomicInteger(0);
|
||||
AtomicInteger consumedCount = new AtomicInteger(0);
|
||||
System.out.println("启动 " + PRODUCER_COUNT + " 个生产者和 " + CONSUMER_COUNT + " 个消费者...");
|
||||
for (int i = 0; i < PRODUCER_COUNT; i++) {
|
||||
final int producerId = i + 1;
|
||||
producerExecutor.submit(() -> {
|
||||
for (int j = 0; j < ITEMS_PER_PRODUCER; j++) {
|
||||
String item = "产品-" + producerId + "-" + (j + 1);
|
||||
queue.putAsync(item).thenRun(() -> {
|
||||
System.out.println("生产者 " + producerId + " 成功放入: " + item);
|
||||
producedCount.incrementAndGet();
|
||||
});
|
||||
try {
|
||||
Thread.sleep((long)(Math.random() * 100));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
for (int i = 0; i < CONSUMER_COUNT; i++) {
|
||||
final int consumerId = i + 1;
|
||||
consumerExecutor.submit(() -> {
|
||||
while (consumedCount.get() < PRODUCER_COUNT * ITEMS_PER_PRODUCER) {
|
||||
queue.takeAsync().thenAccept(item -> {
|
||||
System.out.println("消费者 " + consumerId + " 成功取出: " + item);
|
||||
consumedCount.incrementAndGet();
|
||||
});
|
||||
try {
|
||||
Thread.sleep((long)(Math.random() * 200));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
producerExecutor.shutdown();
|
||||
producerExecutor.awaitTermination(1, TimeUnit.MINUTES);
|
||||
while (consumedCount.get() < PRODUCER_COUNT * ITEMS_PER_PRODUCER) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
System.out.println("\n所有任务完成。");
|
||||
System.out.println("总共生产: " + producedCount.get());
|
||||
System.out.println("总共消费: " + consumedCount.get());
|
||||
consumerExecutor.shutdownNow();
|
||||
}
|
||||
}
|
||||
class AsyncQueue<T> {
|
||||
private final BlockingQueue<T> queue;
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
public AsyncQueue(int capacity) {
|
||||
this.queue = new ArrayBlockingQueue<>(capacity);
|
||||
}
|
||||
public CompletableFuture<Void> putAsync(T item) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
queue.put(item);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("放入队列时被中断", e);
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
public CompletableFuture<T> takeAsync() {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
return queue.take();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("从队列取出时被中断", e);
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
public void shutdown() {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
47
Final/src/multi_thread/AlternatingPrint.java
Normal file
47
Final/src/multi_thread/AlternatingPrint.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package multi_thread;
|
||||
|
||||
public class AlternatingPrint {
|
||||
private final Object lock = new Object();
|
||||
private int number = 1;
|
||||
public static void main(String[] args) {
|
||||
AlternatingPrint printer = new AlternatingPrint();
|
||||
Thread oddThread = new Thread(printer::printOddNumbers, "奇数计数线程");
|
||||
Thread evenThread = new Thread(printer::printEvenNumbers, "偶数计数线程");
|
||||
oddThread.start();
|
||||
evenThread.start();
|
||||
}
|
||||
public void printOddNumbers() {
|
||||
synchronized (lock) {
|
||||
while (number < 100) {
|
||||
while (number % 2 == 0) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("奇数计数线程中断.");
|
||||
}
|
||||
}
|
||||
System.out.println(Thread.currentThread().getName() + ": " + number);
|
||||
number++;
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void printEvenNumbers() {
|
||||
synchronized (lock) {
|
||||
while (number <= 100) {
|
||||
while (number % 2 != 0) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("偶数计数线程中断.");
|
||||
}
|
||||
}
|
||||
System.out.println(Thread.currentThread().getName() + ": " + number);
|
||||
number++;
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
43
Final/src/multi_thread/CountDownLatchDemo.java
Normal file
43
Final/src/multi_thread/CountDownLatchDemo.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package multi_thread;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CountDownLatchDemo {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
int numberOfWorkers = 3;
|
||||
CountDownLatch latch = new CountDownLatch(numberOfWorkers);
|
||||
System.out.println("主线程启动工作线程...");
|
||||
for (int i = 1; i <= numberOfWorkers; i++) {
|
||||
Thread worker = new Thread(new Worker(i, latch));
|
||||
worker.start();
|
||||
}
|
||||
System.out.println("主线程正在等待工作线程结束...");
|
||||
latch.await();
|
||||
System.out.println("所有工作线程结束,主线程继续运行。");
|
||||
}
|
||||
}
|
||||
|
||||
class Worker implements Runnable {
|
||||
private final int id;
|
||||
private final CountDownLatch latch;
|
||||
public Worker(int id, CountDownLatch latch) {
|
||||
this.id = id;
|
||||
this.latch = latch;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
System.out.println("multi_thread.Worker " + id + " 开始工作。");
|
||||
int workTime = (int) (Math.random() * 3000) + 1000;
|
||||
TimeUnit.MILLISECONDS.sleep(workTime);
|
||||
System.out.println("multi_thread.Worker " + id + " 完成工作。");
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("multi_thread.Worker " + id + " 被中断。");
|
||||
} finally {
|
||||
latch.countDown();
|
||||
System.out.println("multi_thread.Worker " + id + " 执行计数器减一. 剩余: " + latch.getCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
55
Final/src/multi_thread/ExecutorServiceDemo.java
Normal file
55
Final/src/multi_thread/ExecutorServiceDemo.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package multi_thread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ExecutorServiceDemo {
|
||||
public static void main(String[] args) {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(3);
|
||||
List<Future<String>> futureList = new ArrayList<>();
|
||||
int numberOfTasks = 5;
|
||||
System.out.println("提交 " + numberOfTasks + " 个任务到线程池...");
|
||||
for (int i = 1; i <= numberOfTasks; i++) {
|
||||
Callable<String> task = new Task(i);
|
||||
Future<String> future = executor.submit(task);
|
||||
futureList.add(future);
|
||||
}
|
||||
System.out.println("所有任务已提交,获取结果...");
|
||||
for (Future<String> future : futureList) {
|
||||
try {
|
||||
String result = future.get();
|
||||
System.out.println(result);
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
System.err.println("获取结果时出错 " + e.getMessage());
|
||||
}
|
||||
}
|
||||
System.out.println("终止 executor service。");
|
||||
executor.shutdown();
|
||||
try {
|
||||
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Task implements Callable<String> {
|
||||
private final int taskId;
|
||||
public Task(int taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
System.out.println("-> 任务 " + taskId + " 运行于线程: " + Thread.currentThread().getName());
|
||||
TimeUnit.MILLISECONDS.sleep((long) (Math.random() * 2000) + 500);
|
||||
return "任务结果: " + taskId;
|
||||
}
|
||||
}
|
||||
74
Final/src/multi_thread/ProducerConsumer.java
Normal file
74
Final/src/multi_thread/ProducerConsumer.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package multi_thread;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.Random;
|
||||
|
||||
public class ProducerConsumer {
|
||||
public static void main(String[] args) {
|
||||
Buffer buffer = new Buffer(5);
|
||||
Thread producerThread = new Thread(() -> {
|
||||
try {
|
||||
for (int i = 0; i < 20; i++) {
|
||||
buffer.produce(i);
|
||||
Thread.sleep(new Random().nextInt(100));
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("生产者被中断。");
|
||||
}
|
||||
}, "生产者");
|
||||
Thread consumerThread = new Thread(() -> {
|
||||
try {
|
||||
for (int i = 0; i < 20; i++) {
|
||||
buffer.consume();
|
||||
// 模拟消费耗时
|
||||
Thread.sleep(new Random().nextInt(250));
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("消费者被中断。");
|
||||
}
|
||||
}, "消费者");
|
||||
producerThread.start();
|
||||
consumerThread.start();
|
||||
try {
|
||||
producerThread.join();
|
||||
consumerThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.err.println("主线程在等待时被中断。");
|
||||
}
|
||||
System.out.println("所有生产和消费任务完成。程序结束。");
|
||||
}
|
||||
}
|
||||
|
||||
class Buffer {
|
||||
private final Queue<Integer> queue;
|
||||
private final int capacity;
|
||||
public Buffer(int capacity) {
|
||||
this.queue = new LinkedList<>();
|
||||
this.capacity = capacity;
|
||||
}
|
||||
public synchronized void produce(int item) throws InterruptedException {
|
||||
while (queue.size() == capacity) {
|
||||
System.out.println("缓冲区已满。" + Thread.currentThread().getName() + " 进入等待状态 (释放锁)...");
|
||||
wait();
|
||||
System.out.println(Thread.currentThread().getName() + " 已被唤醒!");
|
||||
}
|
||||
queue.add(item);
|
||||
System.out.println(Thread.currentThread().getName() + " 生产了: " + item + " (当前容量: " + queue.size() + ")");
|
||||
notifyAll();
|
||||
}
|
||||
public synchronized int consume() throws InterruptedException {
|
||||
while (queue.isEmpty()) {
|
||||
System.out.println("缓冲区为空。" + Thread.currentThread().getName() + " 进入等待状态 (释放锁)...");
|
||||
wait();
|
||||
System.out.println(Thread.currentThread().getName() + " 已被唤醒!");
|
||||
}
|
||||
int item = queue.poll();
|
||||
System.out.println(Thread.currentThread().getName() + " 消费了: " + item + " (当前容量: " + queue.size() + ")");
|
||||
notifyAll();
|
||||
return item;
|
||||
}
|
||||
}
|
||||
26
Final/src/multi_thread/StaticSyncCounter.java
Normal file
26
Final/src/multi_thread/StaticSyncCounter.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package multi_thread;
|
||||
|
||||
public class StaticSyncCounter {
|
||||
private static int count = 0;
|
||||
public static synchronized void increment() {
|
||||
count++;
|
||||
}
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
int numThreads = 10;
|
||||
int incrementsPerThread = 1000;
|
||||
Thread[] threads = new Thread[numThreads];
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
threads[i] = new Thread(() -> {
|
||||
for (int j = 0; j < incrementsPerThread; j++) {
|
||||
increment();
|
||||
}
|
||||
});
|
||||
threads[i].start();
|
||||
}
|
||||
for (Thread thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
System.out.println("期望计数: " + (numThreads * incrementsPerThread));
|
||||
System.out.println("实际计数: " + count);
|
||||
}
|
||||
}
|
||||
87
Final/src/nio/NioChatClient.java
Normal file
87
Final/src/nio/NioChatClient.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package nio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Iterator;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class NioChatClient {
|
||||
private static final int PORT = 8080;
|
||||
private static final String HOST = "127.0.0.1";
|
||||
private static final Charset CHARSET = Charset.forName("UTF-8");
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Selector selector = Selector.open();
|
||||
SocketChannel socketChannel = SocketChannel.open();
|
||||
socketChannel.configureBlocking(false);
|
||||
socketChannel.register(selector, SelectionKey.OP_CONNECT);
|
||||
socketChannel.connect(new InetSocketAddress(HOST, PORT));
|
||||
new Thread(() -> {
|
||||
try (Scanner scanner = new Scanner(System.in)) {
|
||||
System.out.println("请输入要发送的消息...");
|
||||
while (scanner.hasNextLine()) {
|
||||
String message = scanner.nextLine();
|
||||
if (message.length() > 0) {
|
||||
socketChannel.write(CHARSET.encode(message));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("发送消息时发生错误: " + e.getMessage());
|
||||
}
|
||||
}).start();
|
||||
|
||||
while (true) {
|
||||
if (selector.select() == 0) continue;
|
||||
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isConnectable()) {
|
||||
handleConnect(key, selector);
|
||||
} else if (key.isReadable()) {
|
||||
handleRead(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("客户端运行时发生错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
private static void handleConnect(SelectionKey key, Selector selector) throws IOException {
|
||||
SocketChannel channel = (SocketChannel) key.channel();
|
||||
if (channel.isConnectionPending()) {
|
||||
channel.finishConnect();
|
||||
}
|
||||
channel.configureBlocking(false);
|
||||
channel.register(selector, SelectionKey.OP_READ);
|
||||
System.out.println("成功连接到聊天服务器!");
|
||||
}
|
||||
private static void handleRead(SelectionKey key) throws IOException {
|
||||
SocketChannel channel = (SocketChannel) key.channel();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
StringBuilder content = new StringBuilder();
|
||||
try {
|
||||
int readBytes = channel.read(buffer);
|
||||
if (readBytes > 0) {
|
||||
buffer.flip();
|
||||
content.append(CHARSET.decode(buffer));
|
||||
System.out.println(content.toString());
|
||||
} else if (readBytes == -1) {
|
||||
System.out.println("服务器已关闭连接。");
|
||||
key.cancel();
|
||||
channel.close();
|
||||
System.exit(0);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("读取服务器消息时出错,连接已断开。");
|
||||
key.cancel();
|
||||
channel.close();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Final/src/nio/NioChatServer.java
Normal file
109
Final/src/nio/NioChatServer.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package nio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class NioChatServer {
|
||||
private static final int PORT = 8080;
|
||||
private static final String HOST = "127.0.0.1";
|
||||
private static final Charset CHARSET = Charset.forName("UTF-8");
|
||||
private static final ConcurrentHashMap<String, SocketChannel> clients = new ConcurrentHashMap<>();
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Selector selector = Selector.open();
|
||||
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
|
||||
serverSocketChannel.bind(new InetSocketAddress(HOST, PORT));
|
||||
serverSocketChannel.configureBlocking(false);
|
||||
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
|
||||
System.out.println("聊天服务器已启动,监听端口:" + PORT);
|
||||
while (true) {
|
||||
if (selector.select() == 0) continue;
|
||||
Set<SelectionKey> selectedKeys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = selectedKeys.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isAcceptable()) {
|
||||
handleAccept(key, selector);
|
||||
} else if (key.isReadable()) {
|
||||
handleRead(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器运行时发生错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
private static void handleAccept(SelectionKey key, Selector selector) throws IOException {
|
||||
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
|
||||
SocketChannel clientChannel = serverChannel.accept();
|
||||
clientChannel.configureBlocking(false);
|
||||
SelectionKey clientKey = clientChannel.register(selector, SelectionKey.OP_READ);
|
||||
String clientId = UUID.randomUUID().toString();
|
||||
clients.put(clientId, clientChannel);
|
||||
clientKey.attach(clientId);
|
||||
System.out.println("客户端 [" + clientChannel.getRemoteAddress() + "] 连接成功。");
|
||||
broadcastMessage("系统消息:欢迎 " + clientChannel.getRemoteAddress() + " 加入聊天室!当前在线人数:" + clients.size());
|
||||
}
|
||||
private static void handleRead(SelectionKey key) {
|
||||
SocketChannel clientChannel = (SocketChannel) key.channel();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
StringBuilder content = new StringBuilder();
|
||||
try {
|
||||
int readBytes = clientChannel.read(buffer);
|
||||
if (readBytes > 0) {
|
||||
buffer.flip();
|
||||
content.append(CHARSET.decode(buffer));
|
||||
String receivedMessage = content.toString();
|
||||
String address = clientChannel.getRemoteAddress().toString();
|
||||
String broadcastMsg = "来自 " + address + " 的消息: " + receivedMessage;
|
||||
System.out.println(broadcastMsg);
|
||||
broadcastMessage(broadcastMsg, clientChannel);
|
||||
} else if (readBytes == -1) {
|
||||
disconnectClient(key);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
disconnectClient(key);
|
||||
}
|
||||
}
|
||||
private static void broadcastMessage(String message) {
|
||||
broadcastMessage(message, null);
|
||||
}
|
||||
private static void broadcastMessage(String message, SocketChannel excludeChannel) {
|
||||
for (SocketChannel channel : clients.values()) {
|
||||
if (channel.isOpen() && (excludeChannel == null || !channel.equals(excludeChannel))) {
|
||||
try {
|
||||
channel.write(CHARSET.encode(message));
|
||||
} catch (IOException e) {
|
||||
System.err.println("向客户端发送消息失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void disconnectClient(SelectionKey key) {
|
||||
String clientId = (String) key.attachment();
|
||||
SocketChannel clientChannel = (SocketChannel) key.channel();
|
||||
try {
|
||||
String address = clientChannel.getRemoteAddress().toString();
|
||||
key.cancel();
|
||||
clientChannel.close();
|
||||
if (clientId != null) {
|
||||
clients.remove(clientId);
|
||||
}
|
||||
System.out.println("客户端 [" + address + "] 已断开连接。");
|
||||
broadcastMessage("系统消息:" + address + " 离开了聊天室。当前在线人数:" + clients.size());
|
||||
} catch (IOException e) {
|
||||
System.err.println("关闭客户端连接时出错: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
84
Final/src/nio/NioHttpServer.java
Normal file
84
Final/src/nio/NioHttpServer.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package nio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class NioHttpServer {
|
||||
private static final int PORT = 8081;
|
||||
private static final String HOST = "127.0.0.1";
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Selector selector = Selector.open();
|
||||
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
|
||||
serverSocketChannel.bind(new InetSocketAddress(HOST, PORT));
|
||||
serverSocketChannel.configureBlocking(false);
|
||||
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
|
||||
System.out.println("HTTP服务器已启动,监听端口:" + PORT);
|
||||
while (true) {
|
||||
if (selector.select(3000) == 0) {
|
||||
continue;
|
||||
}
|
||||
Set<SelectionKey> selectedKeys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
|
||||
while (keyIterator.hasNext()) {
|
||||
SelectionKey key = keyIterator.next();
|
||||
keyIterator.remove();
|
||||
|
||||
if (key.isAcceptable()) {
|
||||
handleAccept(key, selector);
|
||||
}
|
||||
if (key.isReadable()) {
|
||||
handleRead(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("HTTP服务器运行时发生错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
private static void handleAccept(SelectionKey key, Selector selector) throws IOException {
|
||||
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
|
||||
SocketChannel clientChannel = serverChannel.accept();
|
||||
clientChannel.configureBlocking(false);
|
||||
clientChannel.register(selector, SelectionKey.OP_READ);
|
||||
System.out.println("接收到新的HTTP连接:" + clientChannel.getRemoteAddress());
|
||||
}
|
||||
private static void handleRead(SelectionKey key) throws IOException {
|
||||
SocketChannel clientChannel = (SocketChannel) key.channel();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
try {
|
||||
int bytesRead = clientChannel.read(buffer);
|
||||
if (bytesRead > 0) {
|
||||
buffer.flip();
|
||||
byte[] bytes = new byte[buffer.remaining()];
|
||||
buffer.get(bytes);
|
||||
String request = new String(bytes, StandardCharsets.UTF_8);
|
||||
System.out.println("接收到HTTP请求:\n" + request);
|
||||
|
||||
String responseBody = "<h1>Hello NIO!</h1><p>这是一个基于Java NIO的HTTP服务器响应。</p>";
|
||||
String httpResponse = "HTTP/1.1 200 OK\r\n" +
|
||||
"Content-Type: text/html; charset=utf-8\r\n" +
|
||||
"Content-Length: " + responseBody.getBytes(StandardCharsets.UTF_8).length + "\r\n" +
|
||||
"\r\n" +
|
||||
responseBody;
|
||||
ByteBuffer responseBuffer = ByteBuffer.wrap(httpResponse.getBytes(StandardCharsets.UTF_8));
|
||||
clientChannel.write(responseBuffer);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("处理请求时发生错误: " + e.getMessage());
|
||||
} finally {
|
||||
if (clientChannel != null) {
|
||||
clientChannel.close();
|
||||
}
|
||||
key.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Homework0520/.gitignore
vendored
Normal file
29
Homework0520/.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
10
Homework0520/.idea/.gitignore
generated
vendored
Normal file
10
Homework0520/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# 依赖于环境的 Maven 主目录路径
|
||||
/mavenHomeManager.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
6
Homework0520/.idea/misc.xml
generated
Normal file
6
Homework0520/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
Homework0520/.idea/modules.xml
generated
Normal file
8
Homework0520/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Homework0520.iml" filepath="$PROJECT_DIR$/Homework0520.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
4
Homework0520/.idea/vcs.xml
generated
Normal file
4
Homework0520/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||
</project>
|
||||
11
Homework0520/Homework0520.iml
Normal file
11
Homework0520/Homework0520.iml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
62
Homework0520/src/BufferBasicOperations.java
Normal file
62
Homework0520/src/BufferBasicOperations.java
Normal file
@@ -0,0 +1,62 @@
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class BufferBasicOperations {
|
||||
public static void main(String[] args) {
|
||||
// 创建一个容量为10的ByteBuffer
|
||||
ByteBuffer buffer = ByteBuffer.allocate(10);
|
||||
System.out.println("初始状态:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 向缓冲区依次写入字节1, 2, 3, 4, 5
|
||||
buffer.put((byte) 1);
|
||||
buffer.put((byte) 2);
|
||||
buffer.put((byte) 3);
|
||||
buffer.put((byte) 4);
|
||||
buffer.put((byte) 5);
|
||||
System.out.println("\n写入数据后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 切换为读模式
|
||||
buffer.flip();
|
||||
System.out.println("\n切换为读模式后(flip):");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 读取并打印所有数据
|
||||
System.out.println("\n读取的数据:");
|
||||
while (buffer.hasRemaining()) {
|
||||
byte data = buffer.get();
|
||||
System.out.print(data + " ");
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
System.out.println("\n读取完成后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 清空缓冲区
|
||||
buffer.clear();
|
||||
System.out.println("\n清空缓冲区后(clear):");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 验证是否可重新写入
|
||||
buffer.put((byte) 100);
|
||||
buffer.put((byte) 200);
|
||||
System.out.println("\n重新写入数据后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 验证重新写入的数据
|
||||
buffer.flip();
|
||||
System.out.println("\n验证重新写入的数据:");
|
||||
while (buffer.hasRemaining()) {
|
||||
System.out.print(buffer.get() + " ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// 打印缓冲区状态
|
||||
private static void printBufferStatus(ByteBuffer buffer) {
|
||||
System.out.println("Position: " + buffer.position() +
|
||||
", Limit: " + buffer.limit() +
|
||||
", Capacity: " + buffer.capacity() +
|
||||
", Remaining: " + buffer.remaining());
|
||||
}
|
||||
}
|
||||
65
Homework0520/src/BufferFlipCompact.java
Normal file
65
Homework0520/src/BufferFlipCompact.java
Normal file
@@ -0,0 +1,65 @@
|
||||
import java.nio.CharBuffer;
|
||||
|
||||
public class BufferFlipCompact {
|
||||
public static void main(String[] args) {
|
||||
// 创建一个容量为8的CharBuffer
|
||||
CharBuffer buffer = CharBuffer.allocate(8);
|
||||
System.out.println("初始状态:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 写入字符串"Hello"
|
||||
buffer.put("Hello");
|
||||
System.out.println("\n写入'Hello'后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 翻转缓冲区准备读取
|
||||
buffer.flip();
|
||||
System.out.println("\n翻转缓冲区后(flip):");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 读取前3个字符('H', 'e', 'l')
|
||||
System.out.println("\n读取前3个字符:");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
char c = buffer.get();
|
||||
System.out.print(c + " ");
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
System.out.println("\n读取3个字符后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 压缩缓冲区
|
||||
buffer.compact();
|
||||
System.out.println("\n压缩缓冲区后(compact):");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 再写入"World"
|
||||
buffer.put("World");
|
||||
System.out.println("\n写入'World'后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 翻转并打印最终缓冲区内容
|
||||
buffer.flip();
|
||||
System.out.println("\n最终缓冲区内容:");
|
||||
while (buffer.hasRemaining()) {
|
||||
System.out.print(buffer.get());
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
// 显示完整的缓冲区内容(包括未读取的部分)
|
||||
buffer.rewind(); // 回到开始位置
|
||||
System.out.println("\n完整缓冲区内容:");
|
||||
while (buffer.hasRemaining()) {
|
||||
System.out.print(buffer.get());
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// 打印缓冲区状态
|
||||
private static void printBufferStatus(CharBuffer buffer) {
|
||||
System.out.println("Position: " + buffer.position() +
|
||||
", Limit: " + buffer.limit() +
|
||||
", Capacity: " + buffer.capacity() +
|
||||
", Remaining: " + buffer.remaining());
|
||||
}
|
||||
}
|
||||
105
Homework0520/src/BufferMarkInvalid.java
Normal file
105
Homework0520/src/BufferMarkInvalid.java
Normal file
@@ -0,0 +1,105 @@
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.InvalidMarkException;
|
||||
|
||||
public class BufferMarkInvalid {
|
||||
public static void main(String[] args) {
|
||||
// 创建一个容量为3的IntBuffer
|
||||
IntBuffer buffer = IntBuffer.allocate(3);
|
||||
System.out.println("初始状态:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 依次写入10、20
|
||||
buffer.put(10);
|
||||
buffer.put(20);
|
||||
System.out.println("\n写入10、20后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 在写入20后调用mark()
|
||||
buffer.mark();
|
||||
System.out.println("\n调用mark()后 (position=2):");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 写入30
|
||||
buffer.put(30);
|
||||
System.out.println("\n写入30后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 调用reset(),验证是否能成功
|
||||
try {
|
||||
buffer.reset();
|
||||
System.out.println("\n第一次reset()成功:");
|
||||
printBufferStatus(buffer);
|
||||
System.out.println("mark仍然有效,position回到标记位置2");
|
||||
} catch (InvalidMarkException e) {
|
||||
System.out.println("\n第一次reset()失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
// 清空缓冲区
|
||||
buffer.clear();
|
||||
System.out.println("\n清空缓冲区后(clear):");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 再次调用reset(),观察是否抛出InvalidMarkException
|
||||
try {
|
||||
buffer.reset();
|
||||
System.out.println("\nclear()后reset()成功 - 这不应该发生!");
|
||||
printBufferStatus(buffer);
|
||||
} catch (InvalidMarkException e) {
|
||||
System.out.println("\nclear()后reset()失败 (预期行为):");
|
||||
System.out.println("抛出InvalidMarkException: " + e.getMessage());
|
||||
System.out.println("原因: clear()方法会丢弃mark标记");
|
||||
}
|
||||
|
||||
// 演示其他会使mark失效的操作
|
||||
System.out.println("\n--- 演示其他使mark失效的场景 ---");
|
||||
|
||||
// 重新设置数据和标记
|
||||
buffer.clear();
|
||||
buffer.put(100).put(200);
|
||||
buffer.mark(); // 在position=2处标记
|
||||
buffer.put(300);
|
||||
|
||||
System.out.println("重新设置数据和标记后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 测试rewind()是否影响mark
|
||||
buffer.rewind();
|
||||
System.out.println("\n调用rewind()后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
try {
|
||||
buffer.reset();
|
||||
System.out.println("rewind()后reset()成功 - mark依然有效");
|
||||
printBufferStatus(buffer);
|
||||
} catch (InvalidMarkException e) {
|
||||
System.out.println("rewind()后reset()失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
// 测试flip()是否影响mark
|
||||
buffer.clear();
|
||||
buffer.put(1000).put(2000);
|
||||
buffer.mark(); // 标记
|
||||
buffer.put(3000);
|
||||
|
||||
buffer.flip(); // 准备读取
|
||||
System.out.println("\n调用flip()后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
try {
|
||||
buffer.reset();
|
||||
System.out.println("flip()后reset()成功");
|
||||
printBufferStatus(buffer);
|
||||
} catch (InvalidMarkException e) {
|
||||
System.out.println("flip()后reset()失败: " + e.getMessage());
|
||||
System.out.println("说明: flip()会丢弃mark标记");
|
||||
}
|
||||
}
|
||||
|
||||
// 打印缓冲区状态
|
||||
private static void printBufferStatus(IntBuffer buffer) {
|
||||
System.out.println("Position: " + buffer.position() +
|
||||
", Limit: " + buffer.limit() +
|
||||
", Capacity: " + buffer.capacity() +
|
||||
", Remaining: " + buffer.remaining());
|
||||
}
|
||||
}
|
||||
95
Homework0520/src/BufferMarkReset.java
Normal file
95
Homework0520/src/BufferMarkReset.java
Normal file
@@ -0,0 +1,95 @@
|
||||
import java.nio.CharBuffer;
|
||||
|
||||
public class BufferMarkReset {
|
||||
public static void main(String[] args) {
|
||||
// 创建一个容量为5的CharBuffer
|
||||
CharBuffer buffer = CharBuffer.allocate(5);
|
||||
System.out.println("初始状态:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 写入字符A
|
||||
buffer.put('A');
|
||||
System.out.println("\n写入字符A后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 写入字符B
|
||||
buffer.put('B');
|
||||
System.out.println("\n写入字符B后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 在写入B后调用mark()方法,此时position是2
|
||||
buffer.mark();
|
||||
System.out.println("\n调用mark()后 (position=2):");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 继续写入C、D、E直到缓冲区满
|
||||
buffer.put('C');
|
||||
buffer.put('D');
|
||||
buffer.put('E');
|
||||
System.out.println("\n继续写入C、D、E后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 调用reset()方法,验证position是否回到标记位置
|
||||
buffer.reset();
|
||||
System.out.println("\n调用reset()后:");
|
||||
printBufferStatus(buffer);
|
||||
System.out.println("验证: position已回到标记位置 2");
|
||||
|
||||
// 从position 2开始重新读取并打印后续字符
|
||||
// 首先需要调整limit以便能够读取
|
||||
buffer.limit(5); // 设置limit为容量,允许读取到末尾
|
||||
System.out.println("\n从position 2开始读取后续字符:");
|
||||
while (buffer.hasRemaining()) {
|
||||
char c = buffer.get();
|
||||
System.out.print("字符: " + c + " (position: " + buffer.position() + ")\n");
|
||||
}
|
||||
|
||||
// 演示完整的读取过程
|
||||
System.out.println("\n--- 完整演示 ---");
|
||||
buffer.clear(); // 重置缓冲区
|
||||
|
||||
// 重新写入数据
|
||||
buffer.put('A').put('B');
|
||||
buffer.mark(); // 在position=2处标记
|
||||
buffer.put('C').put('D').put('E');
|
||||
|
||||
// 切换到读模式
|
||||
buffer.flip();
|
||||
System.out.println("切换到读模式后:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 读取所有数据以验证内容
|
||||
System.out.println("完整内容:");
|
||||
while (buffer.hasRemaining()) {
|
||||
System.out.print(buffer.get() + " ");
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
// 注意:flip()方法会丢弃标记,所以需要重新设置
|
||||
// 将position设置到想要标记的位置,然后调用mark()
|
||||
buffer.position(2); // 移动到位置2
|
||||
buffer.mark(); // 重新标记
|
||||
System.out.println("\n重新设置标记在position=2:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 使用reset回到标记位置
|
||||
buffer.reset();
|
||||
System.out.println("\n使用reset()回到标记位置:");
|
||||
printBufferStatus(buffer);
|
||||
|
||||
// 从标记位置开始读取
|
||||
System.out.println("从标记位置开始读取:");
|
||||
while (buffer.hasRemaining()) {
|
||||
System.out.print(buffer.get() + " ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// 打印缓冲区状态
|
||||
private static void printBufferStatus(CharBuffer buffer) {
|
||||
System.out.println("Position: " + buffer.position() +
|
||||
", Limit: " + buffer.limit() +
|
||||
", Capacity: " + buffer.capacity() +
|
||||
", Remaining: " + buffer.remaining());
|
||||
}
|
||||
}
|
||||
163
Homework0520/src/BufferMarkerReader.java
Normal file
163
Homework0520/src/BufferMarkerReader.java
Normal file
@@ -0,0 +1,163 @@
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class BufferMarkerReader {
|
||||
|
||||
/**
|
||||
* 使用ByteBuffer读取一段字节数据的方法
|
||||
* 在读取到特定字节(如0xFF)时设置标记
|
||||
* 继续读取后续字节,直到遇到下一个0xFF
|
||||
* 若未找到第二个0xFF,则回退到标记位置
|
||||
*
|
||||
* @param buffer 要读取的ByteBuffer
|
||||
* @param marker 标记字节,默认为0xFF
|
||||
* @return 读取的字节数组,如果回退则返回null
|
||||
*/
|
||||
public static byte[] readWithMarker(ByteBuffer buffer, byte marker) {
|
||||
if (!buffer.hasRemaining()) {
|
||||
System.out.println("缓冲区没有剩余数据可读");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 查找第一个标记字节
|
||||
boolean firstMarkerFound = false;
|
||||
int markPosition = -1;
|
||||
|
||||
// 寻找第一个0xFF
|
||||
while (buffer.hasRemaining()) {
|
||||
byte currentByte = buffer.get();
|
||||
if (currentByte == marker) {
|
||||
firstMarkerFound = true;
|
||||
markPosition = buffer.position() - 1; // 标记字节的位置
|
||||
buffer.mark(); // 在找到第一个标记后设置mark
|
||||
System.out.println("找到第一个标记字节 0xFF,位置: " + markPosition);
|
||||
System.out.println("设置标记,当前position: " + buffer.position());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!firstMarkerFound) {
|
||||
System.out.println("未找到第一个标记字节 0xFF");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 收集从第一个标记到第二个标记之间的数据
|
||||
ByteBuffer tempBuffer = ByteBuffer.allocate(buffer.remaining() + 1);
|
||||
tempBuffer.put(marker); // 包含第一个标记字节
|
||||
|
||||
// 继续读取,寻找第二个标记字节
|
||||
boolean secondMarkerFound = false;
|
||||
while (buffer.hasRemaining()) {
|
||||
byte currentByte = buffer.get();
|
||||
tempBuffer.put(currentByte);
|
||||
|
||||
if (currentByte == marker) {
|
||||
secondMarkerFound = true;
|
||||
System.out.println("找到第二个标记字节 0xFF,位置: " + (buffer.position() - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (secondMarkerFound) {
|
||||
// 找到第二个标记,返回两个标记之间的数据(包含标记字节)
|
||||
tempBuffer.flip();
|
||||
byte[] result = new byte[tempBuffer.remaining()];
|
||||
tempBuffer.get(result);
|
||||
System.out.println("成功读取数据,长度: " + result.length);
|
||||
return result;
|
||||
} else {
|
||||
// 未找到第二个标记,回退到第一个标记位置
|
||||
try {
|
||||
buffer.reset();
|
||||
System.out.println("未找到第二个标记字节,回退到标记位置");
|
||||
System.out.println("回退后的position值: " + buffer.position());
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
System.out.println("回退失败: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 测试用例1:包含两个0xFF的数据
|
||||
System.out.println("=== 测试用例1:包含两个0xFF的数据 ===");
|
||||
byte[] testData1 = {0x01, 0x02, (byte)0xFF, 0x03, 0x04, 0x05, (byte)0xFF, 0x06, 0x07};
|
||||
ByteBuffer buffer1 = ByteBuffer.wrap(testData1);
|
||||
|
||||
System.out.println("原始数据:");
|
||||
printByteArray(testData1);
|
||||
System.out.println("初始buffer状态:");
|
||||
printBufferStatus(buffer1);
|
||||
|
||||
byte[] result1 = readWithMarker(buffer1, (byte)0xFF);
|
||||
if (result1 != null) {
|
||||
System.out.println("读取结果:");
|
||||
printByteArray(result1);
|
||||
}
|
||||
System.out.println("最终buffer状态:");
|
||||
printBufferStatus(buffer1);
|
||||
|
||||
System.out.println("\n=== 测试用例2:只有一个0xFF的数据 ===");
|
||||
byte[] testData2 = {0x01, 0x02, (byte)0xFF, 0x03, 0x04, 0x05, 0x06};
|
||||
ByteBuffer buffer2 = ByteBuffer.wrap(testData2);
|
||||
|
||||
System.out.println("原始数据:");
|
||||
printByteArray(testData2);
|
||||
System.out.println("初始buffer状态:");
|
||||
printBufferStatus(buffer2);
|
||||
|
||||
byte[] result2 = readWithMarker(buffer2, (byte)0xFF);
|
||||
if (result2 != null) {
|
||||
System.out.println("读取结果:");
|
||||
printByteArray(result2);
|
||||
}
|
||||
System.out.println("最终buffer状态:");
|
||||
printBufferStatus(buffer2);
|
||||
|
||||
System.out.println("\n=== 测试用例3:没有0xFF的数据 ===");
|
||||
byte[] testData3 = {0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
ByteBuffer buffer3 = ByteBuffer.wrap(testData3);
|
||||
|
||||
System.out.println("原始数据:");
|
||||
printByteArray(testData3);
|
||||
|
||||
byte[] result3 = readWithMarker(buffer3, (byte)0xFF);
|
||||
if (result3 != null) {
|
||||
System.out.println("读取结果:");
|
||||
printByteArray(result3);
|
||||
}
|
||||
|
||||
System.out.println("\n=== 测试用例4:连续的0xFF ===");
|
||||
byte[] testData4 = {0x01, (byte)0xFF, (byte)0xFF, 0x02, 0x03};
|
||||
ByteBuffer buffer4 = ByteBuffer.wrap(testData4);
|
||||
|
||||
System.out.println("原始数据:");
|
||||
printByteArray(testData4);
|
||||
|
||||
byte[] result4 = readWithMarker(buffer4, (byte)0xFF);
|
||||
if (result4 != null) {
|
||||
System.out.println("读取结果:");
|
||||
printByteArray(result4);
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:打印字节数组
|
||||
private static void printByteArray(byte[] array) {
|
||||
System.out.print("[");
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
System.out.printf("0x%02X", array[i]);
|
||||
if (i < array.length - 1) {
|
||||
System.out.print(", ");
|
||||
}
|
||||
}
|
||||
System.out.println("]");
|
||||
}
|
||||
|
||||
// 打印缓冲区状态
|
||||
private static void printBufferStatus(ByteBuffer buffer) {
|
||||
System.out.println("Position: " + buffer.position() +
|
||||
", Limit: " + buffer.limit() +
|
||||
", Capacity: " + buffer.capacity() +
|
||||
", Remaining: " + buffer.remaining());
|
||||
}
|
||||
}
|
||||
245
Homework0520/src/BufferVerificationAndThinking.java
Normal file
245
Homework0520/src/BufferVerificationAndThinking.java
Normal file
@@ -0,0 +1,245 @@
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
|
||||
public class BufferVerificationAndThinking {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// (1)如何判断缓冲区是否还有剩余空间?
|
||||
testRemainingSpace();
|
||||
|
||||
System.out.println("\n" + "=".repeat(60));
|
||||
|
||||
// (2)flip() 和 rewind() 的区别
|
||||
testFlipVsRewind();
|
||||
|
||||
System.out.println("\n" + "=".repeat(60));
|
||||
|
||||
// (3)直接缓冲区与非直接缓冲区的性能差异
|
||||
testDirectVsNonDirectBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* (1)测试如何判断缓冲区是否还有剩余空间
|
||||
*/
|
||||
private static void testRemainingSpace() {
|
||||
System.out.println("=== (1)测试缓冲区剩余空间判断 ===");
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(5);
|
||||
System.out.println("创建容量为5的ByteBuffer:");
|
||||
printBufferInfo(buffer);
|
||||
|
||||
// 写入数据测试剩余空间
|
||||
System.out.println("\n逐步写入数据,观察剩余空间变化:");
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
if (buffer.hasRemaining()) {
|
||||
buffer.put((byte) i);
|
||||
System.out.println("写入字节 " + i + " 后:");
|
||||
printBufferInfo(buffer);
|
||||
} else {
|
||||
System.out.println("尝试写入字节 " + i + ": 缓冲区已满,无法写入");
|
||||
printBufferInfo(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 切换到读模式测试剩余数据
|
||||
buffer.flip();
|
||||
System.out.println("\n切换到读模式后:");
|
||||
printBufferInfo(buffer);
|
||||
|
||||
System.out.println("\n逐步读取数据,观察剩余数据变化:");
|
||||
while (buffer.hasRemaining()) {
|
||||
byte data = buffer.get();
|
||||
System.out.println("读取字节 " + data + " 后:");
|
||||
printBufferInfo(buffer);
|
||||
}
|
||||
|
||||
if (!buffer.hasRemaining()) {
|
||||
System.out.println("所有数据已读取完毕");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (2)测试flip()和rewind()的区别
|
||||
*/
|
||||
private static void testFlipVsRewind() {
|
||||
System.out.println("=== (2)flip() 和 rewind() 的区别 ===");
|
||||
|
||||
CharBuffer buffer = CharBuffer.allocate(10);
|
||||
|
||||
// 写入一些数据
|
||||
buffer.put("Hello");
|
||||
System.out.println("写入'Hello'后的状态:");
|
||||
printBufferInfo(buffer);
|
||||
|
||||
// 测试flip()
|
||||
System.out.println("\n--- 测试flip()方法 ---");
|
||||
CharBuffer buffer1 = buffer.duplicate(); // 创建副本用于测试
|
||||
buffer1.flip();
|
||||
System.out.println("调用flip()后:");
|
||||
printBufferInfo(buffer1);
|
||||
System.out.println("flip()的作用: position->0, limit->原position值, 准备从头读取已写入的数据");
|
||||
|
||||
// 读取数据验证flip的效果
|
||||
System.out.println("使用flip()后读取数据:");
|
||||
while (buffer1.hasRemaining()) {
|
||||
System.out.print(buffer1.get());
|
||||
}
|
||||
System.out.println();
|
||||
printBufferInfo(buffer1);
|
||||
|
||||
// 测试rewind()
|
||||
System.out.println("\n--- 测试rewind()方法 ---");
|
||||
CharBuffer buffer2 = buffer.duplicate(); // 创建副本用于测试
|
||||
buffer2.rewind();
|
||||
System.out.println("调用rewind()后:");
|
||||
printBufferInfo(buffer2);
|
||||
System.out.println("rewind()的作用: position->0, limit保持不变, 重新从头开始");
|
||||
|
||||
// 使用rewind后的缓冲区
|
||||
System.out.println("使用rewind()后尝试读取数据 (limit仍为capacity):");
|
||||
int readCount = 0;
|
||||
while (buffer2.hasRemaining() && readCount < 5) { // 只读5个字符,避免读取未初始化数据
|
||||
char c = buffer2.get();
|
||||
if (c != 0) { // 只打印非零字符
|
||||
System.out.print(c);
|
||||
}
|
||||
readCount++;
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
// 关键区别总结
|
||||
System.out.println("\n--- 关键区别总结 ---");
|
||||
System.out.println("flip(): position=0, limit=原position (准备读取已写入的数据)");
|
||||
System.out.println("rewind(): position=0, limit=不变 (重新开始,但limit通常是capacity)");
|
||||
System.out.println("使用场景:");
|
||||
System.out.println(" flip() - 写模式切换到读模式");
|
||||
System.out.println(" rewind() - 重新读取整个缓冲区或重新写入");
|
||||
}
|
||||
|
||||
/**
|
||||
* (3)测试直接缓冲区与非直接缓冲区的性能差异
|
||||
*/
|
||||
private static void testDirectVsNonDirectBuffer() {
|
||||
System.out.println("=== (3)直接缓冲区与非直接缓冲区的性能测试 ===");
|
||||
|
||||
int bufferSize = 1024 * 1024; // 1MB
|
||||
int iterations = 1000;
|
||||
|
||||
// 创建直接缓冲区和非直接缓冲区
|
||||
ByteBuffer directBuffer = ByteBuffer.allocateDirect(bufferSize);
|
||||
ByteBuffer heapBuffer = ByteBuffer.allocate(bufferSize);
|
||||
|
||||
System.out.println("缓冲区大小: " + bufferSize + " 字节");
|
||||
System.out.println("测试迭代次数: " + iterations);
|
||||
System.out.println();
|
||||
|
||||
// 检查缓冲区类型
|
||||
System.out.println("直接缓冲区检查: " + directBuffer.isDirect());
|
||||
System.out.println("堆缓冲区检查: " + heapBuffer.isDirect());
|
||||
System.out.println();
|
||||
|
||||
// 测试写入性能
|
||||
System.out.println("--- 写入性能测试 ---");
|
||||
|
||||
// 测试直接缓冲区写入性能
|
||||
long startTime = System.nanoTime();
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
directBuffer.clear();
|
||||
for (int j = 0; j < bufferSize; j++) {
|
||||
directBuffer.put((byte) (j % 256));
|
||||
}
|
||||
}
|
||||
long directWriteTime = System.nanoTime() - startTime;
|
||||
|
||||
// 测试堆缓冲区写入性能
|
||||
startTime = System.nanoTime();
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
heapBuffer.clear();
|
||||
for (int j = 0; j < bufferSize; j++) {
|
||||
heapBuffer.put((byte) (j % 256));
|
||||
}
|
||||
}
|
||||
long heapWriteTime = System.nanoTime() - startTime;
|
||||
|
||||
System.out.println("直接缓冲区写入时间: " + (directWriteTime / 1_000_000) + " ms");
|
||||
System.out.println("堆缓冲区写入时间: " + (heapWriteTime / 1_000_000) + " ms");
|
||||
System.out.println("写入性能比: " + String.format("%.2f", (double) heapWriteTime / directWriteTime));
|
||||
|
||||
// 测试读取性能
|
||||
System.out.println("\n--- 读取性能测试 ---");
|
||||
|
||||
// 准备数据
|
||||
directBuffer.clear();
|
||||
heapBuffer.clear();
|
||||
for (int i = 0; i < bufferSize; i++) {
|
||||
byte value = (byte) (i % 256);
|
||||
directBuffer.put(value);
|
||||
heapBuffer.put(value);
|
||||
}
|
||||
|
||||
// 测试直接缓冲区读取性能
|
||||
startTime = System.nanoTime();
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
directBuffer.flip();
|
||||
while (directBuffer.hasRemaining()) {
|
||||
directBuffer.get();
|
||||
}
|
||||
directBuffer.rewind();
|
||||
}
|
||||
long directReadTime = System.nanoTime() - startTime;
|
||||
|
||||
// 测试堆缓冲区读取性能
|
||||
startTime = System.nanoTime();
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
heapBuffer.flip();
|
||||
while (heapBuffer.hasRemaining()) {
|
||||
heapBuffer.get();
|
||||
}
|
||||
heapBuffer.rewind();
|
||||
}
|
||||
long heapReadTime = System.nanoTime() - startTime;
|
||||
|
||||
System.out.println("直接缓冲区读取时间: " + (directReadTime / 1_000_000) + " ms");
|
||||
System.out.println("堆缓冲区读取时间: " + (heapReadTime / 1_000_000) + " ms");
|
||||
System.out.println("读取性能比: " + String.format("%.2f", (double) heapReadTime / directReadTime));
|
||||
|
||||
// 性能差异原因分析
|
||||
System.out.println("\n--- 性能差异原因分析 ---");
|
||||
System.out.println("1. 内存分配位置:");
|
||||
System.out.println(" 直接缓冲区: 分配在JVM堆外的本地内存中");
|
||||
System.out.println(" 非直接缓冲区: 分配在JVM堆内存中");
|
||||
|
||||
System.out.println("\n2. I/O操作效率:");
|
||||
System.out.println(" 直接缓冲区: 减少一次内存拷贝 (本地内存 -> 系统调用)");
|
||||
System.out.println(" 非直接缓冲区: 需要额外拷贝 (JVM堆 -> 本地内存 -> 系统调用)");
|
||||
|
||||
System.out.println("\n3. 垃圾回收影响:");
|
||||
System.out.println(" 直接缓冲区: 不受GC直接影响,但清理较复杂");
|
||||
System.out.println(" 非直接缓冲区: 受GC影响,但分配和释放更快");
|
||||
|
||||
System.out.println("\n4. 使用建议:");
|
||||
System.out.println(" 直接缓冲区: 适用于长期存在、频繁I/O操作的大缓冲区");
|
||||
System.out.println(" 非直接缓冲区: 适用于短期、小规模的内存操作");
|
||||
|
||||
// 内存使用情况
|
||||
System.out.println("\n--- 内存使用情况 ---");
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
System.out.println("JVM堆内存使用情况:");
|
||||
System.out.println(" 最大内存: " + (runtime.maxMemory() / 1024 / 1024) + " MB");
|
||||
System.out.println(" 总内存: " + (runtime.totalMemory() / 1024 / 1024) + " MB");
|
||||
System.out.println(" 空闲内存: " + (runtime.freeMemory() / 1024 / 1024) + " MB");
|
||||
System.out.println(" 已用内存: " + ((runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024) + " MB");
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印缓冲区详细信息
|
||||
*/
|
||||
private static void printBufferInfo(java.nio.Buffer buffer) {
|
||||
System.out.println(" Position: " + buffer.position() +
|
||||
" | Limit: " + buffer.limit() +
|
||||
" | Capacity: " + buffer.capacity() +
|
||||
" | Remaining: " + buffer.remaining() +
|
||||
" | HasRemaining: " + buffer.hasRemaining());
|
||||
}
|
||||
}
|
||||
142
Homework0520/src/TicketSystem.java
Normal file
142
Homework0520/src/TicketSystem.java
Normal file
@@ -0,0 +1,142 @@
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class TicketSystem {
|
||||
private int ticketCount = 100; // 初始票数
|
||||
private final ReentrantLock lock = new ReentrantLock(); // 可重入锁
|
||||
private int totalSold = 0; // 已售票数统计
|
||||
|
||||
/**
|
||||
* 卖票方法 - 线程安全
|
||||
*
|
||||
* @param sellerId 售票员ID
|
||||
* @return true表示成功卖出一张票,false表示没有票了
|
||||
*/
|
||||
public boolean sellTicket(String sellerId) {
|
||||
lock.lock(); // 获取锁
|
||||
try {
|
||||
if (ticketCount > 0) {
|
||||
// 模拟卖票过程的耗时
|
||||
try {
|
||||
Thread.sleep(10); // 模拟卖票耗时
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
ticketCount--;
|
||||
totalSold++;
|
||||
int currentTicket = 100 - ticketCount; // 当前卖出的是第几张票
|
||||
|
||||
System.out.println(sellerId + " 卖出第 " + currentTicket + " 张票,剩余票数: " + ticketCount);
|
||||
return true;
|
||||
} else {
|
||||
System.out.println(sellerId + " 尝试卖票,但已无票可售");
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock(); // 确保锁被释放
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取剩余票数
|
||||
*/
|
||||
public int getRemainingTickets() {
|
||||
lock.lock();
|
||||
try {
|
||||
return ticketCount;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已售票数
|
||||
*/
|
||||
public int getTotalSold() {
|
||||
lock.lock();
|
||||
try {
|
||||
return totalSold;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 售票员线程类
|
||||
*/
|
||||
static class TicketSeller implements Runnable {
|
||||
private final TicketSystem ticketSystem;
|
||||
private final String sellerId;
|
||||
|
||||
public TicketSeller(TicketSystem ticketSystem, String sellerId) {
|
||||
this.ticketSystem = ticketSystem;
|
||||
this.sellerId = sellerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println(sellerId + " 开始售票");
|
||||
|
||||
while (true) {
|
||||
boolean sold = ticketSystem.sellTicket(sellerId);
|
||||
if (!sold) {
|
||||
// 没有票了,结束售票
|
||||
break;
|
||||
}
|
||||
|
||||
// 模拟售票间隔
|
||||
try {
|
||||
Thread.sleep(20);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(sellerId + " 结束售票");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
TicketSystem ticketSystem = new TicketSystem();
|
||||
|
||||
System.out.println("=== 卖票系统启动 ===");
|
||||
System.out.println("初始票数: " + ticketSystem.getRemainingTickets());
|
||||
|
||||
// 创建3个售票员线程
|
||||
Thread seller1 = new Thread(new TicketSeller(ticketSystem, "售票员1"));
|
||||
Thread seller2 = new Thread(new TicketSeller(ticketSystem, "售票员2"));
|
||||
Thread seller3 = new Thread(new TicketSeller(ticketSystem, "售票员3"));
|
||||
|
||||
// 启动线程
|
||||
long startTime = System.currentTimeMillis();
|
||||
seller1.start();
|
||||
seller2.start();
|
||||
seller3.start();
|
||||
|
||||
// 等待所有线程结束
|
||||
try {
|
||||
seller1.join();
|
||||
seller2.join();
|
||||
seller3.join();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("主线程被中断");
|
||||
}
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
|
||||
// 输出最终结果
|
||||
System.out.println("\n=== 售票结束 ===");
|
||||
System.out.println("剩余票数: " + ticketSystem.getRemainingTickets());
|
||||
System.out.println("已售票数: " + ticketSystem.getTotalSold());
|
||||
System.out.println("总耗时: " + (endTime - startTime) + " 毫秒");
|
||||
|
||||
// 验证结果
|
||||
if (ticketSystem.getRemainingTickets() == 0 && ticketSystem.getTotalSold() == 100) {
|
||||
System.out.println("✓ 验证成功:所有票都已售出,且没有重复售票");
|
||||
} else {
|
||||
System.out.println("✗ 验证失败:票数统计有误");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
29
NIOChatServ/.gitignore
vendored
Normal file
29
NIOChatServ/.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
10
NIOChatServ/.idea/.gitignore
generated
vendored
Normal file
10
NIOChatServ/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# 依赖于环境的 Maven 主目录路径
|
||||
/mavenHomeManager.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
6
NIOChatServ/.idea/misc.xml
generated
Normal file
6
NIOChatServ/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
NIOChatServ/.idea/modules.xml
generated
Normal file
8
NIOChatServ/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/NIOChatServ.iml" filepath="$PROJECT_DIR$/NIOChatServ.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
4
NIOChatServ/.idea/vcs.xml
generated
Normal file
4
NIOChatServ/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||
</project>
|
||||
11
NIOChatServ/NIOChatServ.iml
Normal file
11
NIOChatServ/NIOChatServ.iml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
255
NIOChatServ/src/client/NioChatClient.java
Normal file
255
NIOChatServ/src/client/NioChatClient.java
Normal file
@@ -0,0 +1,255 @@
|
||||
package client;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class NioChatClient extends JFrame {
|
||||
|
||||
// UI 组件
|
||||
private JTextField hostField;
|
||||
private JTextField portField;
|
||||
private JButton connectButton;
|
||||
|
||||
private JTextArea messageArea; // 显示聊天内容
|
||||
private JTextField inputField; // 输入框
|
||||
private JButton sendButton; // 发送按钮
|
||||
|
||||
// NIO相关
|
||||
private volatile SocketChannel socketChannel;
|
||||
private volatile Selector selector;
|
||||
private volatile boolean running = false; // 用于控制读线程
|
||||
|
||||
private Thread readThread; // 后台读取服务器消息的线程
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
NioChatClient client = new NioChatClient();
|
||||
client.setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造UI
|
||||
*/
|
||||
public NioChatClient() {
|
||||
super("NIO Chat Client");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setSize(600, 400);
|
||||
|
||||
// 主机、端口输入区域
|
||||
JPanel connectPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
connectPanel.add(new JLabel("服务器主机:"));
|
||||
hostField = new JTextField("127.0.0.1", 10);
|
||||
connectPanel.add(hostField);
|
||||
|
||||
connectPanel.add(new JLabel("端口:"));
|
||||
portField = new JTextField("8888", 5);
|
||||
connectPanel.add(portField);
|
||||
|
||||
connectButton = new JButton("连接");
|
||||
connectPanel.add(connectButton);
|
||||
|
||||
// 聊天显示区域
|
||||
messageArea = new JTextArea();
|
||||
messageArea.setEditable(false);
|
||||
JScrollPane scrollPane = new JScrollPane(messageArea);
|
||||
|
||||
// 发送消息区域
|
||||
JPanel inputPanel = new JPanel(new BorderLayout());
|
||||
inputField = new JTextField();
|
||||
sendButton = new JButton("发送");
|
||||
|
||||
inputPanel.add(inputField, BorderLayout.CENTER);
|
||||
inputPanel.add(sendButton, BorderLayout.EAST);
|
||||
|
||||
// 布局
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
getContentPane().add(connectPanel, BorderLayout.NORTH);
|
||||
getContentPane().add(scrollPane, BorderLayout.CENTER);
|
||||
getContentPane().add(inputPanel, BorderLayout.SOUTH);
|
||||
|
||||
// 按钮事件绑定
|
||||
connectButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!running) {
|
||||
connectToServer();
|
||||
} else {
|
||||
disconnectFromServer();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
sendButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
sendMessage(inputField.getText().trim());
|
||||
inputField.setText("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接到服务器
|
||||
*/
|
||||
private void connectToServer() {
|
||||
final String host = hostField.getText().trim();
|
||||
final int port = Integer.parseInt(portField.getText().trim());
|
||||
|
||||
try {
|
||||
// 打开Selector和SocketChannel
|
||||
selector = Selector.open();
|
||||
socketChannel = SocketChannel.open();
|
||||
socketChannel.configureBlocking(false);
|
||||
socketChannel.connect(new InetSocketAddress(host, port));
|
||||
socketChannel.register(selector, SelectionKey.OP_CONNECT);
|
||||
|
||||
// 启动后台线程,处理服务器消息
|
||||
running = true;
|
||||
readThread = new Thread(this::readLoop, "NioClient-ReadThread");
|
||||
readThread.start();
|
||||
|
||||
// 更新UI状态
|
||||
connectButton.setText("断开");
|
||||
appendMessage("正在连接到服务器 " + host + ":" + port + "...\n");
|
||||
} catch (IOException e) {
|
||||
appendMessage("连接失败: " + e.getMessage() + "\n");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开与服务器的连接
|
||||
*/
|
||||
private void disconnectFromServer() {
|
||||
running = false;
|
||||
try {
|
||||
if (socketChannel != null) {
|
||||
socketChannel.close();
|
||||
}
|
||||
if (selector != null) {
|
||||
selector.wakeup();
|
||||
selector.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
socketChannel = null;
|
||||
selector = null;
|
||||
connectButton.setText("连接");
|
||||
appendMessage("已断开连接。\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息给服务器
|
||||
*/
|
||||
private void sendMessage(String msg) {
|
||||
if (!running || socketChannel == null || !socketChannel.isOpen()) {
|
||||
appendMessage("未连接服务器,无法发送消息。\n");
|
||||
return;
|
||||
}
|
||||
if (msg.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
socketChannel.write(ByteBuffer.wrap((msg + "\n").getBytes()));
|
||||
} catch (IOException e) {
|
||||
appendMessage("发送失败: " + e.getMessage() + "\n");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取服务器消息的循环线程
|
||||
*/
|
||||
private void readLoop() {
|
||||
try {
|
||||
while (running && selector != null && selector.isOpen()) {
|
||||
// 阻塞等待事件
|
||||
selector.select();
|
||||
|
||||
// 处理所有就绪事件
|
||||
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
|
||||
while (it.hasNext()) {
|
||||
SelectionKey key = it.next();
|
||||
it.remove();
|
||||
|
||||
if (!key.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 处理连接完成
|
||||
if (key.isConnectable()) {
|
||||
handleConnect(key);
|
||||
}
|
||||
|
||||
// 处理可读
|
||||
if (key.isReadable()) {
|
||||
handleRead(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
appendMessage("读取服务器消息时出现异常: " + e.getMessage() + "\n");
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
// 读线程结束时进行清理
|
||||
disconnectFromServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理连接完成
|
||||
*/
|
||||
private void handleConnect(SelectionKey key) throws IOException {
|
||||
SocketChannel sc = (SocketChannel) key.channel();
|
||||
if (sc.isConnectionPending()) {
|
||||
sc.finishConnect();
|
||||
}
|
||||
sc.configureBlocking(false);
|
||||
sc.register(selector, SelectionKey.OP_READ);
|
||||
appendMessage("已连接到服务器。\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理可读事件:从服务器接收数据
|
||||
*/
|
||||
private void handleRead(SelectionKey key) throws IOException {
|
||||
SocketChannel sc = (SocketChannel) key.channel();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
|
||||
int readBytes = sc.read(buffer);
|
||||
if (readBytes == -1) {
|
||||
// 服务器端关闭
|
||||
appendMessage("服务器已断开连接。\n");
|
||||
running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (readBytes > 0) {
|
||||
buffer.flip();
|
||||
// 按照简单文本协议,读到换行符即可作为一条消息
|
||||
String msg = new String(buffer.array(), 0, buffer.limit()).trim();
|
||||
appendMessage(msg + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在UI文本框中追加消息 (线程安全)
|
||||
*/
|
||||
private void appendMessage(String msg) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
messageArea.append(msg);
|
||||
// 自动滚动到末尾
|
||||
messageArea.setCaretPosition(messageArea.getDocument().getLength());
|
||||
});
|
||||
}
|
||||
}
|
||||
153
NIOChatServ/src/server/NioChatServer.java
Normal file
153
NIOChatServ/src/server/NioChatServer.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class NioChatServer {
|
||||
|
||||
// 维护所有已连接的 SocketChannel
|
||||
private static final ConcurrentHashMap<SocketChannel, String> clientMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 端口可根据需要进行修改
|
||||
int port = 8888;
|
||||
try (Selector selector = Selector.open();
|
||||
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {
|
||||
|
||||
// 配置为非阻塞
|
||||
serverSocketChannel.configureBlocking(false);
|
||||
// 绑定端口
|
||||
serverSocketChannel.bind(new InetSocketAddress(port));
|
||||
// 注册到 selector,监听 "接收新连接" 事件
|
||||
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
System.out.println("服务器已启动,监听端口: " + port);
|
||||
|
||||
// 事件循环
|
||||
while (true) {
|
||||
// 阻塞等待就绪的通道
|
||||
selector.select();
|
||||
// 获取就绪的事件集合
|
||||
Set<SelectionKey> selectionKeys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = selectionKeys.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove(); // 每次处理完一个事件后必须移除,避免重复处理
|
||||
|
||||
try {
|
||||
// 处理新连接
|
||||
if (key.isAcceptable()) {
|
||||
handleAccept(key, selector);
|
||||
}
|
||||
// 处理可读事件
|
||||
if (key.isReadable()) {
|
||||
handleRead(key, selector);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// 发生异常时关闭连接并清理
|
||||
closeChannel(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理新客户端连接
|
||||
*/
|
||||
private static void handleAccept(SelectionKey key, Selector selector) throws IOException {
|
||||
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
|
||||
SocketChannel sc = ssc.accept();
|
||||
if (sc == null) {
|
||||
return;
|
||||
}
|
||||
// 配置为非阻塞
|
||||
sc.configureBlocking(false);
|
||||
// 注册到选择器中,关注读事件
|
||||
sc.register(selector, SelectionKey.OP_READ);
|
||||
// 将此客户端加入管理集合(如果需要,可以存储客户端的名称/ID等信息)
|
||||
clientMap.put(sc, sc.getRemoteAddress().toString());
|
||||
System.out.println("客户端连接: " + sc.getRemoteAddress());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理客户端发送的数据
|
||||
*/
|
||||
private static void handleRead(SelectionKey key, Selector selector) throws IOException {
|
||||
SocketChannel sc = (SocketChannel) key.channel();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
|
||||
int readBytes = sc.read(buffer);
|
||||
// 正常关闭或异常
|
||||
if (readBytes == -1) {
|
||||
closeChannel(key);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果有数据
|
||||
if (readBytes > 0) {
|
||||
buffer.flip();
|
||||
String msg = new String(buffer.array(), 0, buffer.limit()).trim();
|
||||
|
||||
System.out.println("收到消息: " + msg + " 来自: " + clientMap.get(sc));
|
||||
|
||||
// 识别特殊命令
|
||||
if ("EXIT".equalsIgnoreCase(msg)) {
|
||||
// 关闭连接
|
||||
System.out.println("客户端请求断开连接: " + clientMap.get(sc));
|
||||
closeChannel(key);
|
||||
} else if ("PING".equalsIgnoreCase(msg)) {
|
||||
// 回复 PONG
|
||||
String pong = "PONG\n";
|
||||
sc.write(ByteBuffer.wrap(pong.getBytes()));
|
||||
} else {
|
||||
// 普通消息进行广播
|
||||
broadcastMessage(sc, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向其他所有客户端广播消息
|
||||
*/
|
||||
private static void broadcastMessage(SocketChannel sender, String msg) {
|
||||
// 构造广播内容
|
||||
String senderInfo = clientMap.get(sender);
|
||||
String broadcastMsg = "[" + senderInfo + "] " + msg + "\n";
|
||||
|
||||
// 遍历所有连接的客户端, 写入消息
|
||||
clientMap.forEach((channel, info) -> {
|
||||
if (channel != sender && channel.isOpen()) {
|
||||
try {
|
||||
channel.write(ByteBuffer.wrap(broadcastMsg.getBytes()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭通道,清理资源
|
||||
*/
|
||||
private static void closeChannel(SelectionKey key) {
|
||||
try {
|
||||
SocketChannel sc = (SocketChannel) key.channel();
|
||||
System.out.println("连接关闭: " + clientMap.get(sc));
|
||||
clientMap.remove(sc);
|
||||
key.cancel();
|
||||
sc.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
example_src/.gitignore
vendored
Normal file
29
example_src/.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
8
example_src/.idea/.gitignore
generated
vendored
Normal file
8
example_src/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
5
example_src/.idea/misc.xml
generated
Normal file
5
example_src/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
example_src/.idea/modules.xml
generated
Normal file
8
example_src/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Network_Communication.iml" filepath="$PROJECT_DIR$/Network_Communication.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
4
example_src/.idea/vcs.xml
generated
Normal file
4
example_src/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||
</project>
|
||||
11
example_src/Network_Communication.iml
Normal file
11
example_src/Network_Communication.iml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
24
example_src/src/Bus.java
Normal file
24
example_src/src/Bus.java
Normal file
@@ -0,0 +1,24 @@
|
||||
public class Bus implements MyPay,MyInterface2 {
|
||||
|
||||
public void payMoney() {
|
||||
System.out.println("Bus pay money:2元");
|
||||
|
||||
}
|
||||
public void myPrint() {
|
||||
System.out.println("my bus print");
|
||||
|
||||
}
|
||||
public void myMethod() {
|
||||
System.out.println("aggdksjal");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MyInter1Fun() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void MyInter2Fun() {
|
||||
|
||||
}
|
||||
}
|
||||
18
example_src/src/MyDemo1.java
Normal file
18
example_src/src/MyDemo1.java
Normal file
@@ -0,0 +1,18 @@
|
||||
class MyClass1{
|
||||
int a1;
|
||||
int a2;
|
||||
void myPrint(){
|
||||
System.out.println("a1 = " + a1);
|
||||
}
|
||||
}
|
||||
class MyClass2 {
|
||||
int a3;
|
||||
void myPrint(){
|
||||
System.out.println("a3 = " + a3);
|
||||
}
|
||||
}
|
||||
public class MyDemo1 extends MyClass1{
|
||||
|
||||
|
||||
|
||||
}
|
||||
3
example_src/src/MyInterface2.java
Normal file
3
example_src/src/MyInterface2.java
Normal file
@@ -0,0 +1,3 @@
|
||||
public interface MyInterface2 {
|
||||
public void myMethod();
|
||||
}
|
||||
13
example_src/src/MyPay.java
Normal file
13
example_src/src/MyPay.java
Normal file
@@ -0,0 +1,13 @@
|
||||
interface MyInter1{
|
||||
void MyInter1Fun();
|
||||
}
|
||||
interface MyInter2{
|
||||
void MyInter2Fun();
|
||||
|
||||
}
|
||||
public interface MyPay extends MyInter1, MyInter2 {
|
||||
// int x=9;
|
||||
void payMoney();
|
||||
void myPrint();
|
||||
|
||||
}
|
||||
23
example_src/src/MyTest1.java
Normal file
23
example_src/src/MyTest1.java
Normal file
@@ -0,0 +1,23 @@
|
||||
public class MyTest1 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
int a=0;
|
||||
int y=100;
|
||||
int z;
|
||||
try{
|
||||
z=y/a;
|
||||
} catch (ArithmeticException e) {
|
||||
System.out.println("ArithmeticException");
|
||||
z=Integer.MAX_VALUE;
|
||||
System.out.println(z);
|
||||
}
|
||||
|
||||
catch (Exception e) {
|
||||
System.out.println("Exception");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
32
example_src/src/Test1.java
Normal file
32
example_src/src/Test1.java
Normal file
@@ -0,0 +1,32 @@
|
||||
public class Test1 implements Runnable {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
System.out.println("Hello World");
|
||||
Test1 t = new Test1();
|
||||
Thread th1=new Thread(t);
|
||||
th1.setName("Thread1");
|
||||
//th1.run();
|
||||
th1.start();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Thread.sleep(1000);
|
||||
System.out.println("in main");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println("nantongdaxue");
|
||||
System.out.println(Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
14
example_src/src/Test2.java
Normal file
14
example_src/src/Test2.java
Normal file
@@ -0,0 +1,14 @@
|
||||
public class Test2 {
|
||||
public static void main(String[] args) {
|
||||
int a = 0;
|
||||
int y;
|
||||
try{
|
||||
y=3/a;
|
||||
}catch(ArithmeticException e){
|
||||
System.out.println("ArithmeticException");
|
||||
y=Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
System.out.println(y);
|
||||
}
|
||||
}
|
||||
39
example_src/src/Test3.java
Normal file
39
example_src/src/Test3.java
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
class MyThread extends Thread{
|
||||
public void run(){
|
||||
for(int i=0;i<10;i++){
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
}catch(InterruptedException e){
|
||||
System.out.println("InterruptedException");
|
||||
}
|
||||
|
||||
System.out.println("in myThread:"+Thread.currentThread().getName());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class Test3 {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
MyThread t1=new MyThread();
|
||||
t1.setName("t1");
|
||||
t1.start();
|
||||
|
||||
MyThread t2=new MyThread();
|
||||
t2.setName("t2");
|
||||
t2.start();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Thread.sleep(1000);
|
||||
System.out.println("in main:"+Thread.currentThread().getName());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
21
example_src/src/abc/C1.java
Normal file
21
example_src/src/abc/C1.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package abc;
|
||||
|
||||
public class C1 extends Thread{
|
||||
private char ch;
|
||||
private PrintCH pc;
|
||||
|
||||
public C1(char ch, PrintCH pc) {
|
||||
this.ch = ch; this.pc=pc;
|
||||
}
|
||||
public void run(){
|
||||
pc.print(ch);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
PrintCH pc1=new PrintCH();
|
||||
PrintCH pc2=new PrintCH();
|
||||
C1 t1=new C1('A',pc2);
|
||||
C1 t2=new C1('B',pc2);
|
||||
t1.start();
|
||||
t2.start();
|
||||
}
|
||||
}
|
||||
14
example_src/src/abc/PrintCH.java
Normal file
14
example_src/src/abc/PrintCH.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package abc;
|
||||
|
||||
public class PrintCH {
|
||||
public synchronized void print(char c){
|
||||
for(int i=0;i<4;i++){
|
||||
System.out.print(c);
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
example_src/src/hk1/hk1.iml
Normal file
11
example_src/src/hk1/hk1.iml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="17" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
18
example_src/src/hk1/src/demo1/MainTest.java
Normal file
18
example_src/src/hk1/src/demo1/MainTest.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package demo1;
|
||||
|
||||
public class MainTest {
|
||||
public static void main(String[] args) {
|
||||
MyThread1 t1 = new MyThread1();
|
||||
Thread myt1 = new Thread(t1);
|
||||
myt1.start();
|
||||
|
||||
|
||||
MyThread2 t2 = new MyThread2();
|
||||
t2.start();
|
||||
|
||||
System.out.println("this is a main function");
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
19
example_src/src/hk1/src/demo1/MyThread1.java
Normal file
19
example_src/src/hk1/src/demo1/MyThread1.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package demo1;
|
||||
|
||||
public class MyThread1 implements Runnable {
|
||||
|
||||
public void run() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.out.println("this is a car");
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
16
example_src/src/hk1/src/demo1/MyThread2.java
Normal file
16
example_src/src/hk1/src/demo1/MyThread2.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package demo1;
|
||||
|
||||
public class MyThread2 extends Thread {
|
||||
public void run() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.out.println("this is a bus");
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
11
example_src/src/hk2/hk2.iml
Normal file
11
example_src/src/hk2/hk2.iml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="17" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
5
example_src/src/hk2/src/Main.java
Normal file
5
example_src/src/hk2/src/Main.java
Normal file
@@ -0,0 +1,5 @@
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello, World!");
|
||||
}
|
||||
}
|
||||
22
example_src/src/pk1/MyTest.java
Normal file
22
example_src/src/pk1/MyTest.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package pk1;
|
||||
public class MyTest extends Thread{
|
||||
private char ch;
|
||||
private PrintCH2 myprint;
|
||||
public MyTest(char ch, PrintCH2 myprint){
|
||||
this.ch = ch;
|
||||
this.myprint = myprint;
|
||||
}
|
||||
public void run(){
|
||||
synchronized(myprint){
|
||||
myprint.print(ch);
|
||||
}
|
||||
myprint.print(ch);
|
||||
}
|
||||
public static void main(String[] args){
|
||||
PrintCH2 printch2 = new PrintCH2();
|
||||
MyTest t1 = new MyTest('A', myprint);
|
||||
MyTest t2 = new MyTest('B', myprint);
|
||||
t1.start();
|
||||
t2.start();
|
||||
}
|
||||
}
|
||||
49
example_src/src/pk1/pk2/MyThread1.java
Normal file
49
example_src/src/pk1/pk2/MyThread1.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package pk1.pk2;
|
||||
class Thread3 implements Runnable {
|
||||
public void run(){
|
||||
System.out.println("in thread3");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
class MyThread2 extends Thread {
|
||||
public void run() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println("in MyThread2"+Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class MyThread1 {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
MyThread2 t = new MyThread2();
|
||||
t.setName("Thread2");
|
||||
t.start();
|
||||
Thread t2 = new Thread(t);
|
||||
t2.setName("Thread3");
|
||||
t2.start();
|
||||
System.out.println(t2.isAlive());
|
||||
System.out.println(t.isAlive());
|
||||
|
||||
Thread3 th3 = new Thread3();
|
||||
Thread myth3 = new Thread(th3);
|
||||
myth3.setName("MyThread3");
|
||||
myth3.start();
|
||||
|
||||
// Thread myth6 = new Thread("aba");
|
||||
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Thread.sleep(1000);
|
||||
System.out.println("nantongdaxue");
|
||||
}
|
||||
}
|
||||
}
|
||||
29
onetoone/.gitignore
vendored
Normal file
29
onetoone/.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
10
onetoone/.idea/.gitignore
generated
vendored
Normal file
10
onetoone/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# 依赖于环境的 Maven 主目录路径
|
||||
/mavenHomeManager.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
5
onetoone/.idea/misc.xml
generated
Normal file
5
onetoone/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
onetoone/.idea/modules.xml
generated
Normal file
8
onetoone/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/onetoone.iml" filepath="$PROJECT_DIR$/onetoone.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
9
onetoone/.idea/runConfigurations/MyClient.xml
generated
Normal file
9
onetoone/.idea/runConfigurations/MyClient.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="MyClient" type="Application" factoryName="Application" singleton="false" nameIsGenerated="true">
|
||||
<option name="MAIN_CLASS_NAME" value="MyClient" />
|
||||
<module name="onetoone" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
9
onetoone/.idea/runConfigurations/MyServer.xml
generated
Normal file
9
onetoone/.idea/runConfigurations/MyServer.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="MyServer" type="Application" factoryName="Application" nameIsGenerated="true">
|
||||
<option name="MAIN_CLASS_NAME" value="MyServer" />
|
||||
<module name="onetoone" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user