【多线程:综合练习】
01.介绍
我们提出两个问题 分别用wait/notify,park/unpark,await/signal解决。
02.问题一
介绍
我们创建两个线程 从1交替打印到10
wait/notify实现
@Slf4j(topic = "c.TestSun")
public class TestSun {
public static void main(String[] args) {
// 交替打印五轮
TestNumber num = new TestNumber(5);
new Thread(()->{
num.print(true);
},"t1").start();
new Thread(()->{
num.print(false);
},"t2").start();
}
}
@Slf4j(topic = "c.TestNumber")
class TestNumber{
private int cnt = 1;
private boolean flag = true;
private final int count;
public TestNumber(int count){
this.count=count;
}
public void print(boolean flagN){
synchronized (this){
for (int i=0;i<count;i++){
while (flag!=flagN){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("{}",cnt);
cnt++;
flag=!flag;
this.notify();
}
}
}
}
结果
23:45:24.559 c.TestNumber [t1] - 1
23:45:24.562 c.TestNumber [t2] - 2
23:45:24.562 c.TestNumber [t1] - 3
23:45:24.562 c.TestNumber [t2] - 4
23:45:24.562 c.TestNumber [t1] - 5
23:45:24.562 c.TestNumber [t2] - 6
23:45:24.562 c.TestNumber [t1] - 7
23:45:24.562 c.TestNumber [t2] - 8
23:45:24.562 c.TestNumber [t1] - 9
23:45:24.562 c.TestNumber [t2] - 10
park/unpark实现
@Slf4j(topic = "c.TestSunPark")
public class TestSunPark {
static Thread t1;
static Thread t2;
public static void main(String[] args) {
// 交替打印5次
TestParkNum num = new TestParkNum(5);
t1 = new Thread(()->{
num.print(t2);
},"t1");
t2 = new Thread(()->{
num.print(t1);
},"t2");
t1.start();
t2.start();
LockSupport.unpark(t1);
}
}
@Slf4j(topic = "c.TestParkNum")
class TestParkNum{
private int cnt = 1;
private final int count;
public TestParkNum(int count){
this.count=count;
}
public void print(Thread next){
for (int i=0;i<count;i++){
LockSupport.park();
log.debug("{}",cnt);
cnt++;
LockSupport.unpark(next);
}
}
}
结果
23:49:38.354 c.TestSunReenNum [t1] - 1
23:49:38.357 c.TestSunReenNum [t2] - 2
23:49:38.357 c.TestSunReenNum [t1] - 3
23:49:38.357 c.TestSunReenNum [t2] - 4
23:49:38.358 c.TestSunReenNum [t1] - 5
23:49:38.358 c.TestSunReenNum [t2] - 6
23:49:38.358 c.TestSunReenNum [t1] - 7
23:49:38.358 c.TestSunReenNum [t2] - 8
23:49:38.358 c.TestSunReenNum [t1] - 9
23:49:38.358 c.TestSunReenNum [t2] - 10
await/signal实现
public class TestSunReen {
public static void main(String[] args) {
// 交替打印5次
TestSunReenNum num = new TestSunReenNum(5);
Condition condition = num.newCondition();
new Thread(()->{
num.print(true,condition);
},"t1").start();
new Thread(()->{
num.print(false,condition);
},"t2").start();
}
}
@Slf4j(topic = "c.TestSunReenNum")
class TestSunReenNum extends ReentrantLock {
private int cnt = 1;
private final int count;
private boolean flag = true;
TestSunReenNum(int count) {
this.count = count;
}
public void print(boolean flagN, Condition condition){
lock();
try {
for (int i=0;i<count;i++){
while (flag!=flagN){
condition.await();
}
log.debug("{}",cnt);
cnt++;
flag=!flag;
condition.signalAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
unlock();
}
}
}
结果
23:51:38.603 c.TestSunReenNum [t1] - 1
23:51:38.606 c.TestSunReenNum [t2] - 2
23:51:38.606 c.TestSunReenNum [t1] - 3
23:51:38.607 c.TestSunReenNum [t2] - 4
23:51:38.607 c.TestSunReenNum [t1] - 5
23:51:38.607 c.TestSunReenNum [t2] - 6
23:51:38.607 c.TestSunReenNum [t1] - 7
23:51:38.607 c.TestSunReenNum [t2] - 8
23:51:38.607 c.TestSunReenNum [t1] - 9
23:51:38.607 c.TestSunReenNum [t2] - 10
03.问题二
三个线程交替打印abc 5次
wait/notify实现
public class TestSun2 {
public static void main(String[] args) {
TestSun2Num num = new TestSun2Num(5);
new Thread(()->{
num.print("a",1);
}).start();
new Thread(()->{
num.print("b",2);
}).start();
new Thread(()->{
num.print("c",0);
}).start();
}
}
class TestSun2Num{
private int cnt = 1;
private final int count;
public TestSun2Num(int count){
this.count=count;
}
public void print(String str,int flag){
synchronized (this){
for (int i=0;i<count;i++){
while (cnt%3!=flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(str);
if (flag==0)
System.out.println();
cnt++;
this.notifyAll();
}
}
}
}
结果
abc
abc
abc
abc
abc
park/unpark实现
public class TestSun2Park {
static Thread t1;
static Thread t2;
static Thread t3;
public static void main(String[] args) {
TestSun2ParkNum num = new TestSun2ParkNum(5);
t1 = new Thread(()->{
num.print(1,"a",t2);
});
t2 = new Thread(()->{
num.print(2,"b",t3);
});
t3 = new Thread(()->{
num.print(0,"c",t1);
});
t1.start();
t2.start();
t3.start();
LockSupport.unpark(t1);
}
}
class TestSun2ParkNum{
private final int count;
TestSun2ParkNum(int count) {
this.count = count;
}
public void print(int flagN,String str,Thread next){
for (int i=0;i<count;i++){
LockSupport.park();
System.out.print(str);
if (str.equals("c"))
System.out.println();
LockSupport.unpark(next);
}
}
}
结果
abc
abc
abc
abc
abc
await/signal实现
public class TestSun2Reen {
public static void main(String[] args) {
TestReenNum num = new TestReenNum(5);
Condition condition1 = num.newCondition();
Condition condition2 = num.newCondition();
Condition condition3 = num.newCondition();
new Thread(()->{
num.print("a",condition1,condition2);
}).start();
new Thread(()->{
num.print("b",condition2,condition3);
}).start();
new Thread(()->{
num.print("c",condition3,condition1);
}).start();
Sleeper.sleep(1);
num.lock();
try {
condition1.signal();
}finally {
num.unlock();
}
}
}
class TestReenNum extends ReentrantLock {
private final int count;
TestReenNum(int count) {
this.count = count;
}
public void print(String str, Condition condition,Condition nextCondition){
lock();
try {
for (int i=0;i<count;i++){
condition.await();
System.out.print(str);
if (str.equals("c"))
System.out.println();
nextCondition.signalAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
unlock();
}
}
}
结果
abc
abc
abc
abc
abc
04.需要关注的
1.我们需要熟练使用上面几种方法。
2.问题一与问题二用await/signal实现 处理的方式非常不同,可以仔细阅读 分析这两种方法