要求
多线程交替打印1-100
分析
要求两个线程,一个打印奇数,一个打印偶数。考察线程同步和锁相关知识点。
实现
方法1
通过synchronized+对象wait()和notify()
public class Test {
public static void main(String[] args) {
PrintRun printRun = new PrintRun();
Thread thread1 = new Thread(printRun);
thread1.setName("线程1");
Thread thread2 = new Thread(printRun);
thread2.setName("线程2");
thread1.start();
thread2.start();
}
public static class PrintRun implements Runnable{
volatile int i = 1; //需要定义为volatile,保证线程可见性
@Override
public void run() {
while (true){
synchronized (this){
notify(); //调用notify()不会直接唤醒下一个线程,需要等synchronized代码块执行完
System.out.println(Thread.currentThread().getName()+"打印:"+i);
i++;
if (i < 100){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
break;
}
}
}
}
}
}
方法2
使用Lock+Condition
public class Test {
public static void main(String[] args) {
PrintRun printRun = new PrintRun();
Thread thread1 = new Thread(printRun::run);
Thread thread2 = new Thread(printRun::run);
thread1.setName("线程1");
thread2.setName("线程2");
thread1.start();
thread2.start();
}
public static class PrintRun{
private final AtomicInteger count = new AtomicInteger(1); //也可替换成volatile
private final Lock lock = new ReentrantLock();
private final Condition single = lock.newCondition();
private final Condition twin = lock.newCondition();
public void run(){
lock.lock();
try {
while (count.get() <= 100){
if (count.get() % 2 == 1){
System.out.println(Thread.currentThread().getName()+"打印:"+count.get());
twin.signal(); //不会真正唤醒twin,需要等待single释放锁
if (count.incrementAndGet() <= 100){
single.await(); //single等待并释放锁
}
}else {
System.out.println(Thread.currentThread().getName()+"打印:"+count.get());
single.signal();
if (count.incrementAndGet() <= 100){
twin.await();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}