“多线程交替打印”的版本间的差异
		
		
		
		
		
		跳到导航
		跳到搜索
		
				
		
		
	
Jihongchang(讨论 | 贡献)  | 
				Jihongchang(讨论 | 贡献)   | 
				||
| (未显示同一用户的1个中间版本) | |||
| 第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字符<syntaxhighlight lang="java">  | + | 有两个线程,分别打印a字符和b字符  | 
| + | |||
| + | === 代码1: ===  | ||
| + | <syntaxhighlight lang="java">  | ||
import java.util.concurrent.atomic.AtomicInteger;  | import java.util.concurrent.atomic.AtomicInteger;  | ||
| 第66行: | 第69行: | ||
于是线程A跳出while继续执行while外面的notify,然后通知在while中notify了线程A之后wait的线程B继续执行,然后线程A执行结束,线程B也在while判断不成立后跳出循环,执行notify后(因为此时并没有 wait 的线程,所以这个B线程执行的 notify 没什么影响)结束  | 于是线程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工具类。