两个线程同时开启,如果让两个线程顺序执行
- synchronized,然后用 wait notify
- locksupport 的 park,unpark
- cas,不停的去判断另一个线程运行完了没有
- 使用很多种 aqs 实现,如 countdownlatch,semaphore,reentrylock 等
- blockingqueue
- exchanger
- 单一线程池——控制线程顺序运行 8.future 9.pipedinputstram 和 pipedoutputstream
使用join()
join在线程里面意味着“插队”,哪个线程调用join代表哪个线程插队先执行——但是插谁的队是有讲究了,不是说你可以插到队头去做第一个吃螃蟹的人,而是插到在当前运行线程的前面,比如系统目前运行线程A,在线程A里面调用了线程B.join方法,则接下来线程B会抢先在线程A面前执行,等到线程B全部执行完后才继续执行线程A。
而在JDK的解释中,join方法被解释成等待这个线程死亡,也就是等待这个线程全部执行完后才继续执行接下来的进程。

@Test@SneakyThrowspublic void useJoin() {Thread t1 = new Thread(() -> System.out.println(T1_WORD));Thread t2 = new Thread(() -> {try {t1.join(); //插队} catch (InterruptedException e) {e.printStackTrace();}System.out.println(T2_WORD);});t1.start();t2.start();t2.join();}
使用synchronized关键字和 wait¬ify
private static volatile Integer STATUS = 1;@Test@SneakyThrowspublic void useSynchronized() {Object object = new Object();Thread t1 = new Thread(() -> {while (true) {while (STATUS == 1) {synchronized (object) {try {System.out.println(T1_WORD);STATUS = 2;object.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}}, "T1");Thread t2 = new Thread(() -> {while (true) {while (STATUS == 2) {synchronized (object) {try {System.out.println(T2_WORD);TimeUnit.SECONDS.sleep(2);STATUS = 1;object.notify();} catch (InterruptedException e) {e.printStackTrace();}}}}}, "T2");t2.start();t1.start();t2.join();}
使用LockSupport (链接)
@Test@SneakyThrowspublic void useLockSupport() {Thread t2 = new Thread(() -> {LockSupport.park();System.out.println(T2_WORD);});Thread t1 = new Thread(() -> {System.out.println(T1_WORD);try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}LockSupport.unpark(t2);});t1.start();t2.start();t2.join();}
使用CAS
private final AtomicBoolean THREAD_A = new AtomicBoolean(false);@Test@SneakyThrowspublic void useCas() {Thread t1 = new Thread(() -> {System.out.println(T1_WORD);try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}THREAD_A.set(true);});Thread t2 = new Thread(() -> {while (true) {if (THREAD_A.get()) {System.out.println(T2_WORD);break;}}});t1.start();t2.start();t2.join();}
使用很多种 aqs 实现,如 countdownlatch,semaphore,reentrylock 等
CountDownLatch(2021.04.02 修正)
private static final CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(1);@Test@SneakyThrowspublic void useCountDownLatch() {Thread t1 = new Thread(() -> {try {while (true) {while (STATUS == 1) {System.out.println(T1_WORD);COUNT_DOWN_LATCH.countDown();STATUS = 2;COUNT_DOWN_LATCH.await();}}} catch (InterruptedException e) {e.printStackTrace();}});Thread t2 = new Thread(() -> {try {while (true) {while (STATUS == 2) {COUNT_DOWN_LATCH.await();System.out.println(T2_WORD);TimeUnit.SECONDS.sleep(2);STATUS = 1;COUNT_DOWN_LATCH.countDown();}}} catch (InterruptedException e) {e.printStackTrace();}});t1.start();t2.start();t2.join();}
Semaphore(2021.04.02 修正)
private static final Semaphore SEMAPHORE_A = new Semaphore(1);private static final Semaphore SEMAPHORE_B = new Semaphore(0);@SneakyThrows@Testpublic void useSemaphore() {Thread t1 = new Thread(() -> {try {while (true) {SEMAPHORE_A.acquire();System.out.println(T1_WORD);SEMAPHORE_B.release();}} catch (InterruptedException e) {e.printStackTrace();}});Thread t2 = new Thread(() -> {try {while (true) {SEMAPHORE_B.acquire();System.out.println(T2_WORD);System.out.println("-------------------");TimeUnit.SECONDS.sleep(2);SEMAPHORE_A.release();}} catch (InterruptedException e) {e.printStackTrace();}});t1.start();t2.start();t2.join();}
ReentryLock
private static final ReentrantLock REENTRANT_LOCK = new ReentrantLock();
@Test
@SneakyThrows
public void useReentryLock() {
Thread t1 = new Thread(() -> {
try {
REENTRANT_LOCK.lock();
System.out.println(T1_WORD);
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
REENTRANT_LOCK.unlock();
}
});
Thread t2 = new Thread(() -> {
try {
REENTRANT_LOCK.lock();
System.out.println(T2_WORD);
} finally {
REENTRANT_LOCK.unlock();
}
});
t1.start();
t2.start();
t2.join();
}
使用BlockingQueue:take(),put()
private static final BlockingQueue<Integer> BLOCKING_QUEUE = new ArrayBlockingQueue<>(1);
@Test
@SneakyThrows
public void useBlockingQueue() {
Thread t1 = new Thread(() -> {
try {
System.out.println(T1_WORD);
TimeUnit.SECONDS.sleep(3);
BLOCKING_QUEUE.put(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
Integer take = BLOCKING_QUEUE.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(T2_WORD);
});
t1.start();
t2.start();
t2.join();
}
使用Exchanger
private static final Exchanger<Boolean> EXCHANGER = new Exchanger<>();
@Test
@SneakyThrows
public void useExchanger() {
Thread t1 = new Thread(() -> {
System.out.println(T1_WORD);
try {
EXCHANGER.exchange(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
if (EXCHANGER.exchange(false)) {
System.out.println(T2_WORD);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
t2.join();
}
使用单线程池
@Test
@SneakyThrows
public void useSingleThreadPool() {
ExecutorService executor = Executors.newSingleThreadExecutor();
Thread t1 = new Thread(() -> {
System.out.println(T1_WORD);
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
System.out.println(T2_WORD);
COUNT_DOWN_LATCH.countDown();
});
executor.execute(t1);
executor.execute(t2);
COUNT_DOWN_LATCH.await();
executor.shutdown();
}
使用Future
@Test
@SneakyThrows
public void useFuture() {
Future<Void> future = CompletableFuture.runAsync(() -> {
System.out.println(T1_WORD);
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
future.get();
System.out.println(T2_WORD);
}
使用PipedInputStream和PipedOutputStream
@Test
@SneakyThrows
public void usePipedInputStreamAndPipedOutputStream() {
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
pis.connect(pos);
Thread t1 = new Thread(() -> {
System.out.println(T1_WORD);
try {
TimeUnit.SECONDS.sleep(3);
pos.write(T1_WORD.getBytes());
} catch (InterruptedException | IOException e) {
e.printStackTrace();
} finally {
try {
pos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(() -> {
byte[] byteArray = new byte[20];
try {
int readLength = pis.read(byteArray);
while (readLength != -1) {
String newData = new String(byteArray, 0, readLength);
System.out.println("读出数据:" + newData);
readLength = pis.read(byteArray);
}
System.out.println(T2_WORD);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
pis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t2.join();
}
