问题:
有三个线程A、B、C(线程名称或id),循环打印10次ABCABB…
提供四种方法:1、SingleThreadExecutor;2、基于join方法;3、信号量;4、locker锁
方法一:使用SingleThreadExecutor,刚方法表示线程数为1的FixedThreadPool。向SingleThreadExecutor提交的多个任务,会按照它们的提交顺序,并且在下一个任务完成之前完成,因为所有的任务都使用相同的线程。
实现代码:
package cn.rbac.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Demo implements Runnable {
private String threadName;
public Demo() {
}
public Demo(String threadName) {
this.threadName = threadName;
}
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
Thread.currentThread().setName(threadName);
System.out.print(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo demoA = new Demo("A");
Demo demoB = new Demo("B");
Demo demoC = new Demo("C");
ExecutorService exec = Executors.newSingleThreadExecutor();
for(int i=0;i<10;i++){
exec.execute(demoA);
exec.execute(demoB);
exec.execute(demoC);
}
exec.shutdown();
}
}
方法二:使用join方法,思路是:步骤一:在单次循环ABC,为保证顺序,线程C的run执行插入B.join(),线程B的run执行插入A.join();步骤二:为保证每次都是ABC为一个单位依次循环,需要在主线程中加入A.join(),B.join(),C.join(),然后执行循环操作。
代码如下:
package cn.rbac.thread;
public class DemoABC2 {
static class ThreadC extends Thread {
private String name;
private ThreadB threadB;
public ThreadC(String name, ThreadB threadB) {
this.name = name;
this.threadB = threadB;
}
public void run() {
try {
threadB.join();
System.out.print(name);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ThreadB extends Thread {
private String name;
private ThreadA threadA;
public ThreadB(String name, ThreadA threadA) {
this.name = name;
this.threadA = threadA;
}
public void run() {
try {
threadA.join();
System.out.print(name);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ThreadA extends Thread {
private String name;
public ThreadA(String name) {
this.name = name;
}
public void run() {
System.out.print(name);
}
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
ThreadA threada = new ThreadA("A");
ThreadB threadb = new ThreadB("B", threada);
ThreadC threadc = new ThreadC("C", threadb);
threada.start();
threadb.start();
threadc.start();
try {
threada.join();
threadb.join();
threadc.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
方法三:使用lock
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.xml.stream.events.StartDocument;
public class ABC2 {
private static Lock lock = new ReentrantLock();
private static int count = 0;
private static Condition A = lock.newCondition();
private static Condition B = lock.newCondition();
private static Condition C = lock.newCondition();
static class ThreadA extends Thread {
@Override
public void run() {
lock.lock();
try {
for (int i = 0; i < 10; i++) {
while (count % 3 != 0)
A.await(); //如果不满足while条件,将本线程挂起
System.out.print("A");
count++;
B.signal(); // A线程执行后,唤醒下一个线程B
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
static class ThreadB extends Thread {
@Override
public void run() {
lock.lock();
try {
for (int i = 0; i < 10; i++) {
while (count % 3 != 1)
B.await();//如果不满足while条件, 将本线程挂起
System.out.print("B");
count++;
C.signal();// B线程执行后,唤醒下一个线程C
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
static class ThreadC extends Thread {
@Override
public void run() {
lock.lock();
try {
for (int i = 0; i < 10; i++) {
while (count % 3 != 2)
C.await();//如果不满足while条件, 将本线程挂起
System.out.println("C");
count++;
A.signal();// C线程执行后,唤醒下一个线程A
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
ThreadA threadA =new ThreadA();
ThreadB threadB=new ThreadB();
ThreadC threadC = new ThreadC();
threadA.start();
threadB.start();
threadC.start();
threadC.join();//让C线程执行完后在输出cout值否则可能cout在ABC线程都未完成时就输出结果。
System.out.println(count);
}
}
方法四:使用信号量
import java.util.concurrent.Semaphore;
public class ABC3 {
private static Semaphore A = new Semaphore(1);
private static Semaphore B = new Semaphore(1);
private static Semaphore C = new Semaphore(1);
static class ThreadA extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
A.acquire();
System.out.print("A");
B.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ThreadB extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
B.acquire();
System.out.print("B");
C.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ThreadC extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
C.acquire();
System.out.println("C");
A.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
B.acquire();
C.acquire(); // 开始只有A可以获取, BC都不可以获取, 保证了A最先执行
new ThreadA().start();
new ThreadB().start();
new ThreadC().start();
}
}