[******] java多线程连续打印abc
题目描述
建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。
5种方法
- 使用synchronized, wait和notifyAll
- 使用Lock->ReentrantLock 和 state标志
- 使用Lock->ReentrantLock 和Condition(await 、signal、signalAll)
- 使用Semaphore
- 使用AtomicInteger
- 扩展:采用join实现(一次性打印)
5.1 使用synchronized, wait和notifyAll
public class ABC7 { private static Object o = new Object();//所对象 private static int state = 0;//控制顺序 private static int PRINT_NUMBER = 10;//打印次数 private static int THREAD_NUM = 3;//线程数量 static class ThreadGenetic implements Runnable { char name; int data; public ThreadGenetic(char name, int data){ this.name = name; this.data = data; } public void run() { synchronized (o) { for(int i = 0; i < PRINT_NUMBER; ) { if(state % THREAD_NUM == data){//保证顺序 System.out.print(name); ++ state; i++;//注意保证迭代次数 o.notifyAll(); }else{ try { o.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } } public static void main(String[] args) { new Thread(new ThreadGenetic('B',1)).start(); new Thread(new ThreadGenetic('A',0)).start(); new Thread(new ThreadGenetic('C',2)).start(); } }
5.2 使用Lock->ReentrantLock 和 state标志
import java.util.concurrent.locks.ReentrantLock; public class ABC { private static int state = 0;//控制顺序 private static int PRINT_NUMBER = 10;//打印次数 private static int THREAD_NUM = 3;//线程数量 private static ReentrantLock lock = new ReentrantLock();//锁 static class ThreadGenetic extends Thread{ char name; int data; public ThreadGenetic(char name, int data){ this.name = name; this.data = data; } public void run(){ for (int i = 0; i < PRINT_NUMBER; ) {//确保打印次数 lock.lock(); if(state % THREAD_NUM == this.data){//确保按顺序打印 System.out.print(this.name); state++; //确保按顺序打印 i++; //确保打印次数 } lock.unlock(); } } } public static void main(String[] args) { new ThreadGenetic('B',1).start(); new ThreadGenetic('C',2).start(); new ThreadGenetic('A',0).start(); } }
5.3 使用Lock->ReentrantLock 和Condition(await 、signal、signalAll)
方法1
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ABC8 { private static int state = 0;//控制顺序 private static int PRINT_NUMBER = 10;//打印次数 private static int THREAD_NUM = 3;//线程数量 private static ReentrantLock lock = new ReentrantLock();//锁 private static Condition condition = lock.newCondition(); static class ThreadGenetic extends Thread{ char name; int data; public ThreadGenetic(char name, int data){ this.name = name; this.data = data; } public void run(){ lock.lock(); try { for (int i = 0; i < PRINT_NUMBER; ) {//确保打印次数 while(state % THREAD_NUM != data){//确保按顺序打印 condition.await(); } System.out.print(name); state++; //确保按顺序打印 i++; //确保打印次数 condition.signalAll(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } lock.unlock(); } } public static void main(String[] args) { new ThreadGenetic('B',1).start(); new ThreadGenetic('C',2).start(); new ThreadGenetic('A',0).start(); } }
方法2
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ABC2 { private static int state = 0;//控制顺序 private static int PRINT_NUMBER = 10;//打印次数 private static int THREAD_NUM = 3;//线程数量 private static ReentrantLock lock = new ReentrantLock();//锁 private static Condition conditionA = lock.newCondition(); private static Condition conditionB = lock.newCondition(); private static Condition conditionC = lock.newCondition(); static class ThreadGenetic extends Thread{ char name; int data; Condition condition1; Condition condition2; public ThreadGenetic(char name, int data, Condition condition1,Condition condition2){ this.name = name; this.data = data; this.condition1 = condition1; this.condition2 = condition2; } public void run(){ lock.lock(); try { for (int i = 0; i < PRINT_NUMBER; ) {//确保打印次数 while(state % THREAD_NUM != data){//确保按顺序打印 condition1.await(); } System.out.print(name); state++; //确保按顺序打印 i++; //确保打印次数 condition2.signal(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } lock.unlock(); } } public static void main(String[] args) { new ThreadGenetic('B',1,conditionB,conditionC).start(); new ThreadGenetic('C',2,conditionC,conditionA).start(); new ThreadGenetic('A',0,conditionA,conditionB).start(); } }
5.4 使用Semaphore
import java.util.concurrent.Semaphore; public class ABC3 { private static int PRINT_NUMBER = 10;//打印次数 private static Semaphore semaphoreA = new Semaphore(1); private static Semaphore semaphoreB = new Semaphore(1); private static Semaphore semaphoreC = new Semaphore(1); static class ThreadGenetic extends Thread{ char name; int data; Semaphore semaphore1; Semaphore semaphore2; public ThreadGenetic(char name, Semaphore semaphore1,Semaphore semaphore2){ this.name = name; this.semaphore1 = semaphore1; this.semaphore2 = semaphore2; } public void run(){ for (int i = 0; i < PRINT_NUMBER; i++) {//确保打印次数 try { semaphore1.acquire(); System.out.print(name); semaphore2.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { try { semaphoreB.acquire();//保证A先于BC开始 semaphoreC.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } new ThreadGenetic('B',semaphoreB,semaphoreC).start(); new ThreadGenetic('C',semaphoreC,semaphoreA).start(); new ThreadGenetic('A',semaphoreA,semaphoreB).start(); } }
5.5 使用AtomicInteger
import java.util.concurrent.atomic.AtomicInteger; public class ABC5 { private static AtomicInteger atomicinteger = new AtomicInteger(0); private static final int MAX_SYC_VALUE = 3 * 10; static class ThreadGenetic extends Thread { char name; int data; public ThreadGenetic(char name, int data) { this.name = name; this.data = data; } public void run() { while (atomicinteger.get() < MAX_SYC_VALUE-1) { if (atomicinteger.get() % 3 == data) { System.out.print(name); atomicinteger.getAndIncrement(); } } } } public static void main(String[] args) { new ThreadGenetic('B', 1).start(); new ThreadGenetic('C', 2).start(); new ThreadGenetic('A', 0).start(); } }
5.6 采用join实现(一次性打印)
public class ABC6 { public static void main(String[] args) { // 线程A final Thread a = new Thread(new Runnable() { @Override public void run() { System.out.println("A"); } }); // 线程B final Thread b = new Thread(new Runnable() { @Override public void run() { try { // 执行b线程之前,加入a线程,让a线程执行 a.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("B"); } }); // 线程C final Thread c = new Thread(new Runnable() { @Override public void run() { try { // 执行c线程之前,加入b线程,让b线程执行 b.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("C"); } }); // 启动三个线程 a.start(); b.start(); c.start(); } }