java多线程实现A到Z和1到26按顺序输出,比如1A2B3C4D......
今天研究了一下,控制两个线程交替执行输出,一个输出1-26,一个输出A到Z.
用了6种方法实现:
1:使用synchronized,wait,notify
package ef.thread;
/**
* @author :sunshine
* @date :Created in 2021/7/20 16:13
* @description:AZ26
*/
public class AZ26 {
public static void main(String[] args) {
final Object lock = new Object();
Thread t1 = new Thread(() -> {
int i = 1;
synchronized (lock) {
while (i <= 26) {
System.out.println(i);
i++;
try {
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify();//必须,否则无法停止程序,因为最后肯定有个在wait
}
});
Thread t2 = new Thread(() -> {
char i = 'A';
synchronized (lock) {
while (i <= 'Z') {
System.out.println(i);
i++;
try {
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify();//必须,否则无法停止程序,因为最后肯定有个在wait
}
});
t1.start();
t2.start();
}
}
2:使用volatile,保证线程可见性
package ef.thread;
/**
* @author :sunshine
* @date :Created in 2021/7/20 16:13
* @description:AZ26
*/
public class AZ262 {
static volatile boolean thread2Run = false;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
int i = 1;
while(i <= 26){
System.out.println(i);
i++;
thread2Run = true;
while(true){
if(!thread2Run) break;
}
}
});
Thread t2 = new Thread(() -> {
char i = 'A';
while(i <= 'Z'){
while(thread2Run){
System.out.println(i);
i++;
thread2Run = false;
break;
}
}
});
t1.start();
t2.start();
}
}
3:使用ReentrantLock的Condition
package ef.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author :sunshine
* @date :Created in 2021/7/21 10:18
* @description:AZ263
*/
public class AZ263 {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Thread t1 = new Thread(() -> {
int i = 1;
lock.lock();
while (i <= 26) {
System.out.println(i);
i++;
try {
c2.signal(); //唤醒线程2
c1.await(); //等待且释放线程1当前的锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
c2.signal(); //唤醒线程2,必须,否则无法停止程序,因为最后肯定有个在wait
lock.unlock();
});
Thread t2 = new Thread(() -> {
char i = 'A';
lock.lock();
while (i <= 'Z') {
System.out.println(i);
i++;
try {
c1.signal(); //唤醒线程1
c2.await(); //等待且释放线程2当前的锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
c1.signal(); //唤醒线程2,必须,否则无法停止程序,因为最后肯定有个在wait
lock.unlock();
});
t1.start();
t2.start();
}
}
4:使用LockSupport
package ef.thread;
import java.util.concurrent.locks.LockSupport;
/**
* @author :sunshine
* @date :Created in 2021/7/21 10:18
* @description:AZ263
*/
public class AZ264 {
static Thread t1 = null, t2 = null;
public static void main(String[] args) {
t1 = new Thread(() -> {
int i = 1;
while(i <= 26){
System.out.println(i);
LockSupport.unpark(t2); //t2可以跑了
LockSupport.park(); //t1停住等待
i++;
}
});
t2 = new Thread(() -> {
char i = 'A';
while(i <= 'Z'){
LockSupport.park(); //t2等待
System.out.println(i);
LockSupport.unpark(t1); //t1可以跑了,t2挺住等待
i++;
}
});
t1.start();
t2.start();
}
}
5:使用semaphore
package ef.thread;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
/**
* @author :sunshine
* @date :Created in 2021/7/26 17:24
* @description:AZ265
*/
public class AZ265 {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(2);
Semaphore semaphore = new Semaphore(1, true);
// semaphore只是控制信号量,每次只能被固定数量的线程拿到,不公平的话,被谁拿到不一定
// 所以这里用锁控制两个线程都启动后再开始执行公平的争抢信号量
Thread t1 = new Thread(() -> {
latch.countDown(); // 门闩减1
try {
latch.await(); // 等待门闩=0开始执行
int i = 1;
while (i <= 26) {
semaphore.acquire();
System.out.println(i);
semaphore.release();
i++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
latch.countDown(); // 门闩减1
try {
latch.await(); // 等待门闩=0开始执行
char i = 'A';
while (i <= 'Z') {
semaphore.acquire();
System.out.println(i);
semaphore.release();
i++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
}
6:使用SynchronousQueue(容量永远为0,且阻塞)
package ef.thread;
import java.util.concurrent.SynchronousQueue;
/**
* @author :sunshine
* @date :Created in 2021/7/21 10:18
* @description:AZ266
*/
public class AZ266 {
public static void main(String[] args) {
SynchronousQueue<Integer> sq1 = new SynchronousQueue<>();
SynchronousQueue<Character> sq2 = new SynchronousQueue<>();
Thread t1 = new Thread(() -> {
try {
int i = 1;
while (i <= 26) {
sq1.put(i);
System.out.println(sq2.take());
i++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
char i = 'A';
while (i <= 'Z') {
System.out.println(sq1.take());// 保证先打印1
sq2.put(i);
i++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
}
目前只想到这几种方法,都可以实现这个功能,有其他更好的方案,欢迎讨论。