多線程順序打印100個數
一、前言
昨天群友問了個有意思的問題
多線程打印1-100,線程1打印123,線程2打印456,線程3答應789,以此類推 不能出現亂序
故今天實現一番
二、實現
本人的思路是為每個線程編號, 定義公共變量nextPrintThreadSeq表示將要打印的線程編號, 以此來保證有序
/** * 多線程打印1-100,線程1打印123,線程2打印456,線程3答應789,以此類推 不能出現亂序 * @author TimFruit * @date 20-4-25 上午8:41 */ public class LockPrintOneHundred { //通過序號來保證線程順序 //下一個將要打印的線程序號 private static volatile int nextPrintThreadSeq=0; //每個線程起始打印的數字 private static volatile int eachStartNumber=1; private static Lock lock=new ReentrantLock(); public static void main(String[] args) { int nThread=3; List<Thread> threads=new ArrayList<>(); Thread thread; for(int i=0;i<nThread;i++){ thread=new Thread(new PrintRunnable(i, nThread)); threads.add(thread); thread.start(); } //等待線程結束 threads.forEach(t-> { try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } }); } static class PrintRunnable implements Runnable{ private int seq;//當前線程序號 private int nThread;//線程總數 public PrintRunnable(int seq,int nThread) { this.seq = seq; this.nThread=nThread; } @Override public void run() { while(true && eachStartNumber<=100){ while (nextPrintThreadSeq!=seq){ LockSupport.parkNanos(100);//停頓等待 } lock.lock(); if(nextPrintThreadSeq!=seq){//再次判斷 lock.unlock(); continue; } int n=eachStartNumber; for(int i=0; i<3 & n<=100; i++,n++){ System.out.println("threadSeq: "+seq+", number: "+n); } //修改狀態 eachStartNumber+=3; nextPrintThreadSeq=(seq+1)%nThread; lock.unlock(); } } } }
三、附其他人的實現
public class SemaphoreOneHundred { static final Semaphore sem = new Semaphore(1); static int state = 0; static int count = 0; static class ThreadA implements Runnable { @Override public void run() { try { while (count <= 100) { while (state % 3 != 0) { sem.release(); } sem.acquire(); for (int j = 0; j < 3 && count<100; j++) { count++; System.out.println("A " + count); } state++; sem.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } static class ThreadB implements Runnable { @Override public void run() { try { while (count <= 100) { while (state % 3 != 1) { sem.release(); } sem.acquire(); for (int j = 0; j < 3 && count<100; j++) { count++; System.out.println("B " + count); } state++; sem.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } static class ThreadC implements Runnable { @Override public void run() { try { while (count <= 100) { while (state % 3 != 2) { sem.release(); } sem.acquire(); for (int j = 0; j < 3 && count<100; j++) { count++; System.out.println("C " + count); } state++; sem.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { new Thread(new ThreadA()).start(); new Thread(new ThreadB()).start(); new Thread(new ThreadC()).start(); } }