Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<spring-boot-starter-web.version>3.4.5</spring-boot-starter-web.version>
<guava.version>33.4.0-jre</guava.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<fastjson.version>2.0.12</fastjson.version>
</properties>

<dependencies>
Expand All @@ -37,6 +38,7 @@
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>

<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand All @@ -56,6 +58,12 @@
<version>${commons-lang3.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package multi_threading.fixed_operating_sequence;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
* Require always to run the t2 thread first before running other threads.
*/
public class FixedOperatingSequenceByLock {
private static final ReentrantLock lock = new ReentrantLock();
private static final Condition cond = lock.newCondition();
private static boolean ready = false;

public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
try {
lock.lock();
while (!ready) {
try {
cond.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
} finally {
lock.unlock();
}
System.out.println("t1 run...");
}, "t1").start();

new Thread(() -> {
try {
lock.lock();
System.out.println("t2 run...");
ready = true;
cond.signal();
} finally {
lock.unlock();
}
}, "t2").start();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package multi_threading.fixed_operating_sequence;

import java.util.concurrent.locks.LockSupport;

/**
* Require always to run the t2 thread first before running other threads.
*/
public class FixedOperatingSequenceByPark {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
LockSupport.park();
System.out.println("t1 run...");
}, "t1");
t1.start();

new Thread(() -> {
System.out.println("t2 run...");
LockSupport.unpark(t1);
}, "t2").start();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package multi_threading.fixed_operating_sequence;

/**
* Require always to run the t2 thread first before running other threads.
*/
public class FixedOperatingSequenceByWaitNotify {
private static final Object obj = new Object();
private static boolean ready = false;

public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
synchronized (obj) {
while (!ready) {
try {
obj.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("t1 run...");
}
}, "t1").start();

new Thread(() -> {
synchronized (obj) {
System.out.println("t2 run...");
ready = true;
obj.notify();
}
}, "t2").start();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package multi_threading.guarded_suspension;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;

import java.util.List;

public class GuardedSuspensionMod {

@SuppressWarnings("unchecked")
public static void main(String[] args) {
GuardObject guardObject = new GuardObject();
new Thread(() -> {
System.out.println("waiting for result...");
// List<String> o = (List<String>) guardObject.get();
// List<String> o = (List<String>) guardObject.get(100);
List<String> o = (List<String>) guardObject.get(3000);
System.out.println(STR."result:\{JSONObject.toJSONString(o)}");
}, "t1").start();

new Thread(() -> {
System.out.println("process downloading...");
guardObject.complete(new Download().downloadMock());
}, "t2").start();
}

}

class GuardObject {
private Object response;

public Object get() {
synchronized (this) {
while (response == null) {
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return response;
}
}

/**
* Waiting with timeout period,
* The principle of the join method in Thread
*
* @param timeout
* @return
*/
public Object get(long timeout) {
synchronized (this) {
long begin = System.currentTimeMillis();
// elapsed time
long passTime = 0;
while (response == null) {
try {
// the time to wait for this cycle
long waitTime = timeout - passTime;
if (waitTime <= 0) {
break;
}
this.wait(waitTime);
passTime = System.currentTimeMillis() - begin;
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return response;
}
}

public void complete(Object response) {
synchronized (this) {
this.response = response;
this.notifyAll();
}
}
}

class Download {
public List<String> downloadMock() {
try {
//mock download progress
Thread.sleep(2500);
return buildMockResult();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

private List<String> buildMockResult() {
String s = "success";
List<String> res = Lists.newArrayList();
res.add(s);
return res;
}
}
16 changes: 16 additions & 0 deletions src/main/java/multi_threading/producer_consumer/Message.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package multi_threading.producer_consumer;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class Message {
private int id;
private String value;

@Override
public String toString() {
return STR."Message{id=\{id}, value='\{value}'}";
}
}
44 changes: 44 additions & 0 deletions src/main/java/multi_threading/producer_consumer/MessageQueue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package multi_threading.producer_consumer;

import com.google.common.collect.Lists;

import java.util.List;

public class MessageQueue {
public int capacity = 10;

private final List<Message> queue = Lists.newArrayList();

public Message take() {
synchronized (queue) {
while (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
Message message = queue.removeFirst();
queue.notifyAll();
return message;
}
}

public void put(Message message) {
synchronized (queue) {
while (queue.size() >= capacity) {
try {
queue.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
queue.add(message);
queue.notifyAll();
}
}

public int size() {
return queue.size();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package multi_threading.thread_alternate_running;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadAlternateRunningByLock {
public static void main(String[] args) throws InterruptedException {
AwaitSignal awaitSignalObj = new AwaitSignal(5);
Condition a = awaitSignalObj.newCondition();
Condition b = awaitSignalObj.newCondition();
Condition c = awaitSignalObj.newCondition();

new Thread(() -> {
awaitSignalObj.process("a", a, b);
}, "t1").start();
new Thread(() -> {
awaitSignalObj.process("b", b, c);
}, "t2").start();
new Thread(() -> {
awaitSignalObj.process("c", c, a);
}, "t3").start();

Thread.sleep(1000);
try {
awaitSignalObj.lock();
a.signal();
} finally {
awaitSignalObj.unlock();
}
}
}

class AwaitSignal extends ReentrantLock {
private final int loopNumber;

public AwaitSignal(int loopNumber) {
this.loopNumber = loopNumber;
}

public void process(String str, Condition current, Condition next) {
for (int i = 0; i < loopNumber; i++) {
lock();
try {
current.await();
System.out.print(str);
next.signal();
} catch (InterruptedException e) {
// Thread.currentThread().interrupt(); // restore interrupted state
throw new RuntimeException(e);
} finally {
unlock();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package multi_threading.thread_alternate_running;

import java.util.concurrent.locks.LockSupport;

public class ThreadAlternateRunningByPark {
static Thread t1;
static Thread t2;
static Thread t3;
public static void main(String[] args) {
ParkUnpark parkUnparkObj = new ParkUnpark(5);
t1 = new Thread(() -> {
parkUnparkObj.process("a", t2);
}, "t1");
t2 = new Thread(() -> {
parkUnparkObj.process("b", t3);
}, "t2");
t3 = new Thread(() -> {
parkUnparkObj.process("c", t1);
}, "t3");
t1.start();
t2.start();
t3.start();

LockSupport.unpark(t1);
}
}

class ParkUnpark {
private final int loopNumber;
ParkUnpark(int loopNumber) {
this.loopNumber = loopNumber;
}

public void process(String str, Thread t) {
for (int i = 0; i < loopNumber; i++) {
LockSupport.park();
System.out.print(str);
LockSupport.unpark(t);
}
}
}
Loading