线程交替执行的实践
线程交替执行的实践 也就是 1a2b3c4d交替输出的问题
- 只能保证交替执行, 至于先输出1 还是先输出A 谁先抢到o锁谁就输出
public class Syncwaitnotify1 {
public static void main(String[] args) {
final Object o = new Object();
char[] aI = "123456789".toCharArray();
char[] aC = "ABCDEFGHI".toCharArray();
new Thread(()->{
//1. 先拿到o锁
synchronized (o) {
for(char c : aI) {
//2. 执行
System.out.print(c);
try {
o.notify();//唤醒线程队列中得下一个线程, 这里只有两个,就相当于唤醒另一个
o.wait();//让出锁,重新进入等待队列
}catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t1").start();
new Thread(()->{
//1. 和上面得Thread强锁
synchronized (o) {
for(char i : aC) {
System.out.print(i);
try {
o.notify();
o.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t2").start();
}
}
- 先等待一直等到CountDownLatch计数器为0, 所以这个程序一定先输出A
import java.util.concurrent.CountDownLatch;
public class Syncwaitnotify2 {
/*
CountDownLatch latch = new CountDownLatch(n);
latch.countDown();每执行一次,n-1
*/
private static CountDownLatch latch = new CountDownLatch(1);
public static void main(String[] args) {
final Object o = new Object();
char[] aI = "123456789".toCharArray();
char[] aC = "ABCDEFGHI".toCharArray();
new Thread(()->{
try{
latch.await();
}catch (InterruptedException e) {
e.printStackTrace();
}
//1. 先拿到o锁
synchronized (o) {
for(char c : aI) {
//2. 执行
System.out.print(c);
try {
o.notify();//唤醒线程队列中得下一个线程, 这里只有两个,就相当于唤醒另一个
o.wait();//让出锁,重新进入等待队列
}catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t1").start();
new Thread(()->{
//1. 和上面得Thread强锁
synchronized (o) {
for(char i : aC) {
System.out.print(i);
latch.countDown();
try {
o.notify();
o.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t2").start();
}
}
- 通过volatile 实现 volatile是原子操作并且线程可见,也可以保证顺序执行
/**
* 如果t1先拿到锁,此时t25 = false 在while中不断得会让出锁
* 等t2拿到锁后, 设置t25=true就可以正常交替执行了
*/
public class Syncwaitnotify3 {
private static volatile boolean t25 = false;
public static void main(String[] args) {
final Object o = new Object();
char[] aI = "123456789".toCharArray();
char[] aC = "ABCDEFGHI".toCharArray();
new Thread(()->{
//1. 如果t1先拿到锁
synchronized (o) {
//2. 此时t25=false
while (!t25) {
try {
//3. 让出线程, 进入等待队列
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(char c : aI) {
System.out.print(c);
try {
o.notify();//唤醒线程队列中得下一个线程, 这里只有两个,就相当于唤醒另一个
o.wait();//让出锁,重新进入等待队列
}catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t1").start();
new Thread(()->{
//4. 此时t2后拿到锁
synchronized (o) {
for(char i : aC) {
System.out.print(i);
t25 = true;
try {
o.notify();
o.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t2").start();
}
}
- 指定线程锁,相互唤醒,第一次也使用latch.await(); 保证, 和2差不多
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockCondition {
public static void main(String[] args) {
char[] aI = "123456789".toCharArray();
char[] aC = "ABCDEFGHI".toCharArray();
Lock lock = new ReentrantLock();
Condition conditionT1 = lock.newCondition();
Condition conditionT2 = lock.newCondition();
CountDownLatch latch = new CountDownLatch(1);
new Thread(()->{
try {
//1. 启动线程直接进入等待
latch.await();
}catch (InterruptedException e) {
e.printStackTrace();
}
lock.lock();
try {
for(char c : aI) {
System.out.print(c);
conditionT2.signal();
conditionT1.await();
}
conditionT2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "t1").start();
new Thread(()->{
lock.lock();
try {
//2. 线程启动直接进入循环进行输出
for(char c : aC) {
System.out.print(c);
//3. 标记完成
latch.countDown();
//4. 唤醒conditionT1队列
conditionT1.signal();
conditionT2.await();
}
conditionT1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "t2").start();
}
}
- LockSupport的实现
import java.util.concurrent.locks.LockSupport;
public class LockSupport1 {
static Thread t1=null, t2=null;
public static void main(String[] args) {
char[] aI = "123456789".toCharArray();
char[] aC = "ABCDEFGHI".toCharArray();
t1 = new Thread(() -> {
for(char c: aI) {
LockSupport.park();
System.out.print(c);
LockSupport.unpark(t2);
}
},"t1");
t2 = new Thread(() -> {
for(char c: aC) {
System.out.print(c);
LockSupport.unpark(t1);
LockSupport.park();
}
},"t2");
t1.start();
t2.start();
}
}
- TransferQueue的实现
import java.util.concurrent.LinkedTransferQueue;
public class TransferQueue1 {
public static void main(String[] args) {
char[] aI = "123456789".toCharArray();
char[] aC = "ABCDEFGHI".toCharArray();
java.util.concurrent.TransferQueue<Character> queue = new LinkedTransferQueue<>();
new Thread(() ->{
try{
for(char c: aI) {
System.out.print(queue.take());
queue.transfer(c);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t1").start();
new Thread(() ->{
try{
for(char c: aC) {
queue.transfer(c);
System.out.print(queue.take());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t2").start();
}
}