java 多线程轮流打印数字

方法一:通过 synchronized 锁和 wait notify的方式实现

 public class ThreadTest {

    // 方式一,通过 synchronized 锁和 wait notify的方式实现
    public static void main(String[] args) {
        // 当前需要执行线程编号 0 1 2
        AtomicInteger executeThreadNo = new AtomicInteger(0);
        // 打印起始的 i 值
        AtomicInteger printI = new AtomicInteger(1);
        //总线程数
        int total = 3;
        Thread t1 = new Thread(new PrintRunnable(0, executeThreadNo, total, printI));
        Thread t2 = new Thread(new PrintRunnable(1, executeThreadNo, total, printI));
        Thread t3 = new Thread(new PrintRunnable(2, executeThreadNo, total, printI));
        t2.start();
        t1.start();
        t3.start();
    }


  class PrintRunnable implements Runnable {
    // 当前线程序号
    private int threadNo;
    private AtomicInteger executeThreadNo;
    private int total;
    private AtomicInteger printI;

    public PrintRunnable(int threadNo, AtomicInteger executeThreadNo, int total, AtomicInteger printI) {
        this.threadNo = threadNo;
        this.executeThreadNo = executeThreadNo;
        this.total = total;
        this.printI = printI;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (executeThreadNo) {
                try {
                    // 若当前线程和需要执行的线程不等,则需要等待
                    while (executeThreadNo != null && threadNo != executeThreadNo.get()) {
                        // wait后会释放锁
                        executeThreadNo.wait();
                    }
                } catch (InterruptedException e) {
                    System.out.println("中断异常");
                }
                // 若i>100,唤醒并返回
                if (printI.get() <= 100) {
                    System.out.println(Thread.currentThread().getName() + "****** " + printI.get());
                    // 自增 i
                    printI.addAndGet(1);
                    // 计算需要执行的线程编号,通过取余的方式完成
                    executeThreadNo.set((executeThreadNo.get() + total + 1) % total);
                    // 唤醒线程
                    executeThreadNo.notifyAll();
                } else {
                    executeThreadNo.set((executeThreadNo.get() + total + 1) % total);
                    executeThreadNo.notifyAll();
                    return;
                }
            }
        }
    }
  }

方法二:通过可重入锁和condition条件的方式实现

public class ThreadTest2 {

    // 方式二,通过可重入锁和condition条件的方式实现
    public static void main(String[] args) {
        // 锁
        ReentrantLock lock = new ReentrantLock();
        // 当前需要执行线程编号
        AtomicInteger executeThreadNo = new AtomicInteger(0);
        // 打印起始的 i 值
        AtomicInteger printI = new AtomicInteger(1);
        //总线程数
        int total = 3;
        // 线程1等待条件
        Condition c1 = lock.newCondition();
        // 线程2等待条件
        Condition c2 = lock.newCondition();
        // 线程3等待条件
        Condition c3 = lock.newCondition();
        Thread t1 = new Thread(new PrintRunnable2(lock, c1, c2, c3, 0, executeThreadNo, total, printI));
        Thread t2 = new Thread(new PrintRunnable2(lock, c1, c2, c3, 1, executeThreadNo, total, printI));
        Thread t3 = new Thread(new PrintRunnable2(lock, c1, c2, c3, 2, executeThreadNo, total, printI));
        t2.start();
        t1.start();
        t3.start();
    }
}

class PrintRunnable2 implements Runnable {

    private ReentrantLock reentrantLock;
    private Condition c1;
    private Condition c2;
    private Condition c3;
    private int threadNo;
    private AtomicInteger executeThreadNo;
    private int total;
    private AtomicInteger printI;

    public PrintRunnable2(ReentrantLock reentrantLock, Condition c1, Condition c2, Condition c3, int threadNo, AtomicInteger executeThreadNo, int total, AtomicInteger printI) {
        this.reentrantLock = reentrantLock;
        this.c1 = c1;
        this.c2 = c2;
        this.c3 = c3;
        this.threadNo = threadNo;
        this.executeThreadNo = executeThreadNo;
        this.total = total;
        this.printI = printI;
    }

    @Override
    public void run() {
        while (true) {
            try {
                // 加锁
                reentrantLock.lock();
                // 当前线程和需要执行的线程不等,则通过对应条件等待
                if (executeThreadNo.get() != threadNo) {
                    if (threadNo == 0) {
                        c1.await();
                    } else if (threadNo == 1) {
                        c2.await();
                    } else if (threadNo == 2) {
                        c3.await();
                    }
                }
                // 若i>100,唤醒并返回
                if (printI.get() <= 100) {
                    System.out.println(Thread.currentThread().getName() + "****** " + printI.get());
                    printI.addAndGet(1);
                    // 计算需要执行的线程编号,通过取余的方式完成
                    executeThreadNo.set((executeThreadNo.get() + total + 1) % total);
                } else {
                    return;
                }
            } catch (InterruptedException e) {
                System.out.println("中断异常");
            } finally {
                // 唤醒和释放锁
                signal();
            }
        }
    }

    // 唤醒
    private void signal() {
        if (threadNo == 0) {
            c2.signal();
        } else if (threadNo == 1) {
            c3.signal();
        } else {
            c1.signal();
        }
        reentrantLock.unlock();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值