“多线程交替打印”的版本间的差异
跳到导航
跳到搜索
Jihongchang(讨论 | 贡献) |
Jihongchang(讨论 | 贡献) |
||
(未显示同一用户的2个中间版本) | |||
第1行: | 第1行: | ||
https://www.bilibili.com/video/BV1ez421C7Fz/?spm_id_from=333.999.0.0&vd_source=92b1acbb084e38873b05857f8f1b9289 | https://www.bilibili.com/video/BV1ez421C7Fz/?spm_id_from=333.999.0.0&vd_source=92b1acbb084e38873b05857f8f1b9289 | ||
− | 有两个线程,分别打印a字符和b字符 | + | 有两个线程,分别打印a字符和b字符 |
− | |||
+ | === 代码1: === | ||
+ | <syntaxhighlight lang="java"> | ||
import java.util.concurrent.atomic.AtomicInteger; | import java.util.concurrent.atomic.AtomicInteger; | ||
第56行: | 第57行: | ||
* 这单独的一个notify调用是为了通知另一个还在while里wait的线程 | * 这单独的一个notify调用是为了通知另一个还在while里wait的线程 | ||
*/ | */ | ||
− | |||
} | } | ||
+ | monitor.notify(); | ||
} | } | ||
} | } | ||
} | } | ||
+ | </syntaxhighlight>会有一个线程,我们假定它是A,先进入synchronized块,然后执行到wait释放锁(执行notify的时候并有其他在wait的线程,所以无所谓); | ||
− | </syntaxhighlight> | + | 这时候另一个线程,我们叫它B,就可以进入synchronized一直执行到notify通知 wait的线程A 继续执行,之后线程B wait; |
+ | |||
+ | 然后就是A、B两个线程交替执行,直到有一个线程,我们假定是线程A 执行完wait之后,又被线程B nofity之后 继续执行,到 while 中的判断不再成立, | ||
+ | |||
+ | 于是线程A跳出while继续执行while外面的notify,然后通知在while中notify了线程A之后wait的线程B继续执行,然后线程A执行结束,线程B也在while判断不成立后跳出循环,执行notify后(因为此时并没有 wait 的线程,所以这个B线程执行的 notify 没什么影响)结束 | ||
+ | |||
+ | |||
+ | 代码2: | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | import java.util.concurrent.atomic.AtomicInteger; | ||
+ | import java.util.concurrent.locks.Condition; | ||
+ | import java.util.concurrent.locks.Lock; | ||
+ | import java.util.concurrent.locks.ReentrantLock; | ||
+ | |||
+ | public class MultiPrint3 { | ||
+ | |||
+ | public static void main(String[] args) throws InterruptedException { | ||
+ | AtomicInteger i = new AtomicInteger(0); | ||
+ | Lock lock = new ReentrantLock(); | ||
+ | Condition condition = lock.newCondition(); | ||
+ | Runnable pr = new NewPrintRunnable(lock, condition, i, 100); | ||
+ | Thread t1 = new Thread(pr); | ||
+ | Thread t2 = new Thread(pr); | ||
+ | t1.start(); | ||
+ | t2.start(); | ||
+ | // 得t1和t2都执行完才能结束 | ||
+ | t1.join(); | ||
+ | System.out.println(t1.getId() + "结束"); | ||
+ | // 得t1和t2都执行完才能结束 | ||
+ | t2.join(); | ||
+ | System.out.println(t2.getId() + "结束"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class NewPrintRunnable implements Runnable { | ||
+ | |||
+ | private final Lock lock; | ||
+ | private final Condition condition; | ||
+ | private AtomicInteger i; | ||
+ | private int end; | ||
+ | |||
+ | /** | ||
+ | * @param monitor | ||
+ | * @param i | ||
+ | * @param end | ||
+ | */ | ||
+ | public NewPrintRunnable(Lock lock, Condition condition, AtomicInteger i, int end) { | ||
+ | super(); | ||
+ | this.lock = lock; | ||
+ | this.condition = condition; | ||
+ | this.i = i; | ||
+ | this.end = end; | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void run() { | ||
+ | long id = Thread.currentThread().getId(); | ||
+ | lock.lock(); | ||
+ | while (i.get() < end) { | ||
+ | System.out.println(id + ":" + i.incrementAndGet()); | ||
+ | try { | ||
+ | condition.signal(); | ||
+ | condition.await(); | ||
+ | } catch (InterruptedException e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | } | ||
+ | condition.signal(); | ||
+ | lock.unlock(); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight>代码2与代码1的实现思路是一样的,代码2使用了JDK1.5加入的Lock和Condition这些JUC工具类。 |
2024年7月7日 (日) 03:19的最新版本
有两个线程,分别打印a字符和b字符
代码1:
import java.util.concurrent.atomic.AtomicInteger;
public class MultiPrint2 {
public static void main(String[] args) throws InterruptedException {
Object monitor = new Object();
AtomicInteger i = new AtomicInteger(0);
PrintRunnable pr = new PrintRunnable(monitor, i, 100);
Thread t1 = new Thread(pr);
Thread t2 = new Thread(pr);
t1.start();
t2.start();
//得t1和t2都执行完才能结束
t1.join();
System.out.println(t1.getId() + "结束");
//得t1和t2都执行完才能结束
t2.join();
System.out.println(t2.getId() + "结束");
}
}
class PrintRunnable implements Runnable {
private Object monitor;
private AtomicInteger i;
private int end;
/**
* @param monitor
* @param i
* @param end
*/
public PrintRunnable(Object monitor, AtomicInteger i, int end) {
super();
this.monitor = monitor;
this.i = i;
this.end = end;
}
@Override
public void run() {
long id = Thread.currentThread().getId();
synchronized (monitor) {
while (i.get() < end) {
System.out.println(id + ":" + i.incrementAndGet());
try {
monitor.notify();
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
* notify要在synchronized里,不然会抛IllegalMonitorStateException
* 这单独的一个notify调用是为了通知另一个还在while里wait的线程
*/
}
monitor.notify();
}
}
}
会有一个线程,我们假定它是A,先进入synchronized块,然后执行到wait释放锁(执行notify的时候并有其他在wait的线程,所以无所谓);
这时候另一个线程,我们叫它B,就可以进入synchronized一直执行到notify通知 wait的线程A 继续执行,之后线程B wait;
然后就是A、B两个线程交替执行,直到有一个线程,我们假定是线程A 执行完wait之后,又被线程B nofity之后 继续执行,到 while 中的判断不再成立,
于是线程A跳出while继续执行while外面的notify,然后通知在while中notify了线程A之后wait的线程B继续执行,然后线程A执行结束,线程B也在while判断不成立后跳出循环,执行notify后(因为此时并没有 wait 的线程,所以这个B线程执行的 notify 没什么影响)结束
代码2:
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MultiPrint3 {
public static void main(String[] args) throws InterruptedException {
AtomicInteger i = new AtomicInteger(0);
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
Runnable pr = new NewPrintRunnable(lock, condition, i, 100);
Thread t1 = new Thread(pr);
Thread t2 = new Thread(pr);
t1.start();
t2.start();
// 得t1和t2都执行完才能结束
t1.join();
System.out.println(t1.getId() + "结束");
// 得t1和t2都执行完才能结束
t2.join();
System.out.println(t2.getId() + "结束");
}
}
class NewPrintRunnable implements Runnable {
private final Lock lock;
private final Condition condition;
private AtomicInteger i;
private int end;
/**
* @param monitor
* @param i
* @param end
*/
public NewPrintRunnable(Lock lock, Condition condition, AtomicInteger i, int end) {
super();
this.lock = lock;
this.condition = condition;
this.i = i;
this.end = end;
}
@Override
public void run() {
long id = Thread.currentThread().getId();
lock.lock();
while (i.get() < end) {
System.out.println(id + ":" + i.incrementAndGet());
try {
condition.signal();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
condition.signal();
lock.unlock();
}
}
代码2与代码1的实现思路是一样的,代码2使用了JDK1.5加入的Lock和Condition这些JUC工具类。