方法1,使用wait和notify
package com.thread;
public class T01 {
public static void main(String[] args) {
char[] char1 = "AAAAAA".toCharArray();
char[] char2 = "BBBBBB".toCharArray();
Object object = new Object();
Thread thread1 = new Thread(() -> {
synchronized(object){//使用notify和wait時,必須要選獲取到鎖
for (int i = 0; i < char1.length; i++) {
try {
System.out.print(char1[i]);
object.notify();
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
object.notify();//必須加上,否則程序無法結束,兩個線程總有一個最後是wait狀態,所以此處必須加
}
},"t1");
Thread thread2 = new Thread( () -> {
synchronized(object){
for (int i = 0; i < char2.length; i++) {
try {
System.out.print(char2[i]);
object.notify();
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
object.notify();
}
},"t2");
thread1.start();
thread2.start();
}
}
方法2,使用LockSupport方法
package com.thread;
import java.util.concurrent.locks.LockSupport;
public class T02 {
static Thread thread1 ;
static Thread thread2 ;
public static void main(String[] args) {
char[] char1 = "AAAAAA".toCharArray();
char[] char2 = "BBBBBB".toCharArray();
thread1 = new Thread(() -> {
for (int i = 0; i < char1.length; i++) {
System.out.print(char1[i]);
LockSupport.unpark(thread2);
LockSupport.park();
}
},"t1");
thread2 = new Thread(() -> {
for (int i = 0; i < char2.length; i++) {
LockSupport.park();
System.out.print(char2[i]);
LockSupport.unpark(thread1);
}
},"t2");
thread1.start();
thread2.start();
}
}
方法3,使用CAS自旋鎖
package com.thread;
public class T03 {
enum ReadEnum{
T1,
T2;
}
static volatile ReadEnum r = ReadEnum.T1;
public static void main(String[] args) {
char[] char1 = "AAAAAA".toCharArray();
char[] char2 = "BBBBBB".toCharArray();
Thread thread1 = new Thread(() ->{
for (int i = 0; i < char1.length; i++) {
while (r != ReadEnum.T1) {
}
System.out.print(char1[i]);
r = ReadEnum.T2;
}
},"t1");
Thread thread2 = new Thread(() ->{
for (int i = 0; i < char2.length; i++) {
while (r != ReadEnum.T2) {
}
System.out.print(char2[i]);
r = ReadEnum.T1;
}
},"t2");
thread1.start();
thread2.start();
}
}
方法4,使用Condition方法
package com.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class T04 {
public static void main(String[] args) {
char[] char1 = "AAAAAA".toCharArray();
char[] char2 = "BBBBBB".toCharArray();
ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Thread thread1 = new Thread(() ->{
try {
lock.lock();
for (int i = 0; i < char1.length; i++) {
System.out.print(char1[i]);
condition2.signal();//喚醒線程2執行
condition1.await();//線程1等待
}
condition2.signal();
}catch (Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
}
},"t1");
Thread thread2 = new Thread(() ->{
try {
lock.lock();
for (int i = 0; i < char2.length; i++) {
System.out.print(char2[i]);
condition1.signal();
condition2.await();
}
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
}
},"t2");
thread1.start();
thread2.start();
}
}
打印結果:
Condition與notify相比的好處是,Condition可以指定需要喚醒的線程,而notify是無法指定的,只能隨機喚醒一個或者全喚醒(notifyAll)