实现三个线程交替打印1-100的四种姿势

使用synchronized关键字

synchronized关键字常用写法

使用synchronized关键字的写法比较多,常用的有如下几种

public class UseSync{
    // 持有的锁是UseSync.java 对应的Class类的对象
    synchronized public static void testMethod() {
    }
    // 持有的锁是UseSync.java 对应的Class类的对象
    public void testMethod2() {
        synchronized (UseSync.class) {
            
        }
    }
    // 持有的锁是UseSync.java类的对象
    synchronized public void testMethod3() {
        
    }
    // 持有的锁是UseSync.java类的对象
    public void testMethod4() {
        synchronized (this) {

        }
    }
    // 持有的锁是字符串abc类的对象
    public void testMethod5() {
        synchronized ("abc") {

        }
    }
    
}

交替打印

锁是非this对象(例子使用object)

  1. 实现Runnable
class PrintSequence implements Runnable {

    int numOfThreads;

    static int  count=1;

    static Object monitor = new Object(); //static
    public PrintSequence( int nubOfThreads) {
        this.numOfThreads = nubOfThreads;
    }

    @Override
    public void run() {
        print();
    }

    private void print() {

        while (count<99) {
            synchronized (monitor) {
                while(count % 3 != numOfThreads) {
                    try {
                        monitor.wait();
                    } catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }

                System.out.println("ThreadId [" + numOfThreads
                        + "] printing -->"
                        + count);
                count++;
                monitor.notifyAll();

            }


        }

    }

}
  1. 运行类
public class Test {


    public static void main(String[] args) {

        PrintSequence runnable1=new PrintSequence(1);
        PrintSequence runnable2=new PrintSequence(2);
        PrintSequence runnable3=new PrintSequence(0);

        Thread t1=new Thread(runnable1,"T1");
        Thread t2=new Thread(runnable2,"T2");
        Thread t3=new Thread(runnable3,"T3");

        t1.start();
        t2.start();
        t3.start();
    }


}

锁是持有对应的Class类的对象

  1. 继承Thread的方法创建线程A
public class ThreadA extends Thread {
    private Service s ;
    public ThreadA(Service s) {
        this.s = s;
    }

    @Override
    public void run() {
        s.printCount(this.getName());
    }
}
  1. 实现Runnable的方法创建线程C
public class RunnableC implements Runnable {
    private Service s ;
    public RunnableC(Service s) {
        this.s = s;
    }

    @Override
    public void run() {
        s.printCount2(Thread.currentThread().getName());
    }
}
  1. 封装Service。
public class Service {
    private volatile static int count;
    public Service(int count){
        this.count = count;
    }

    public void printCount(String threadName) {
        synchronized (Service.class) {
            if (count <=100) {
                System.out.println("Thread " + Thread.currentThread().getName() + " = " + count ++ );
            }

        }

    }

    public void printCount2(String threadName) {
        synchronized (Service.class) {
           if (count <=100) {
               System.out.println("Thread " + Thread.currentThread().getName() + " = " + count++);
           }
        }


    }

}
  1. 运行类代码如下
public class Print3 {
    public static void main(String[] args) throws InterruptedException {
        int count = 1;
        Service s = new Service(count);

        for ( int i=0; i< 34;i++) {
            ThreadA a = new ThreadA(s);
            a.setName("A");

            Thread b = new Thread("B") {
                @Override
                public void run() {
                    s.printCount(this.getName());
                }
            };
            Runnable r = new RunnableC(s);
            Thread c = new Thread(r, "C");
            
            a.start();
            a.join();
            b.start();
            b.join();
            c.start();
        }
    }

}

如果注释掉Print3.java中的join(), 可用于验证当锁是持有对应的Class类的对象时,同步方法呈现同步效果。即运行完一个同步方法才会运行下一个同步方法。注意,3 个线程调用顺序是random,但是结果是同步的。

如果想保持A B C 顺序,可以使用join()。 方法join()具有串联执行的作用:你不销毁,我不往下走,可以支持多个线程的等待。 join()在内部使用wait()方法进行等待,会释放锁,而synchronized关键字一直持有锁。

使用ReentrantLock 和 Condition

  1. 封装Service
public class MyService{
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    volatile private int nextWhoPrint = 1;
    volatile private int count = 1;


    public void testMethod1() {
        try {
            lock.lock();
            while(nextWhoPrint!=1) {
                condition.await();
            }
            if (count <=100) {
                System.out.println("Thread A " + count++);
            }
            nextWhoPrint = 2;
            condition.signalAll();
            lock.unlock();
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void testMethod2() {
        try {
            lock.lock();
            while(nextWhoPrint!=2) {
                condition.await();
            }
            if (count <=100) {
                System.out.println("Thread B " + count++);
            }
            nextWhoPrint = 3;
            condition.signalAll();
            lock.unlock();
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void testMethod3() {
        try {
            lock.lock();
            while(nextWhoPrint!=3) {
                condition.await();
            }
            if (count <=100) {
                System.out.println("Thread C " + count++);
            }
            nextWhoPrint = 1;
            condition.signalAll();
            lock.unlock();
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  1. 创建3个线程
public class MyThreadA extends Thread {
    private MyService service;
    public MyThreadA(MyService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.testMethod1();
    }
}
public class MyThreadB extends Thread {
    private MyService service;
    public MyThreadB(MyService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.testMethod2();
    }
}
class MyThreadC extends Thread {
    private MyService service;
    public MyThreadC(MyService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        service.testMethod3();
    }
}
  1. 创建运行类
public class Lock3 {
    public static void main(String[] args) throws InterruptedException {
        MyService service  =new MyService();
        for( int i=0;i<34;i++) {
            MyThreadA a = new MyThreadA(service);
            a.start();
            MyThreadB b = new MyThreadB(service);
            b.start();
            MyThreadC c = new MyThreadC(service);
            c.start();
        }
    }
}

使用信号量

public class ThreadPrint100 {
    // 以A开始的信号量,初始信号量数量为1
    private static final Semaphore A = new Semaphore(1);
    // B、C信号量,A完成后开始,初始信号数量为0
    private static final Semaphore B = new Semaphore(0);
    private static final Semaphore C = new Semaphore(0);
    private volatile static  int count = 1;

    //设置一个控制变量
    private static boolean  loop = true;

    public static class ThreadA extends Thread {

        @Override
        public void run() {
            try {
                for (int i = 0; i < 34  && loop ; i++) {
                    A.acquire();// A获取信号执行,A信号量减1,当A为0时将无法继续获得该信号量

                    System.out.println("Thread A: " + count);
                    count ++;
                    B.release();// B释放信号,B信号量加1(初始为0),此时可以获取B信号量
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static class ThreadB extends Thread {
        @Override
        public void run() {
            try {
                for (int i = 0; i <33 && loop; i++) {
                    B.acquire();
                    System.out.println("Thread B: " + count);
                    count ++;
                    C.release();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static class ThreadC extends Thread {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 33 && loop; i++) {
                    C.acquire();
                    System.out.println("Thread C: " + count);
                    count ++;
                    A.release();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new ThreadA().start();
        new ThreadB().start();
        new ThreadC().start();
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值