• 两个线程,一个输出字母一个输出数字,输出A1B2C3....Z26


    思路1 :用一个变量记录属于哪个线程执行,然后另外一个线程阻塞掉即可。

    public class main {
        static volatile int a = 1;
        public static void main(String[] args) {
            new  Thread(new Runnable() {
                @Override
                public void run() {
                    for(int i = 0 ; i < 26 ; i++){
                        while(a % 2 == 1){
                            try {
                                Thread.currentThread().interrupt();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println(a/2);
                        a = a+1;
                    }
                }
            }).start();
            new  Thread(new Runnable() {
                @Override
                public void run() {
                    for(int i = 0 ; i < 26 ; i++){
                        while(a % 2 == 0){
                            try {
                                Thread.currentThread().interrupt();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println((char)((a/2)+'A'));
                        a = a+1;
                    }
                }
            }).start();
        }
    }

    思路2 :使用LockSupport中的unpark和park方法唤醒对方线程并阻塞当前线程。

    import java.util.concurrent.locks.LockSupport;
    
    public class Test_LockSupport {
        static Thread t1 = null,t2 = null;
        public static void main(String[] args) {
            char []aI = "123456789".toCharArray();
            char []aC = "ABCDEFJHI".toCharArray();
            t1 = new Thread(()->{
                for (char c : aI) {
                    System.out.println(c);
                    LockSupport.unpark(t2);//唤醒t2
                    LockSupport.park();//阻塞t1
                }
            },"t1");
            t2 = new Thread(()->{
                for (char c : aC) {
                    LockSupport.park();//阻塞t2,等着t1叫醒它
                    System.out.println(c);
                    LockSupport.unpark(t1);//唤醒t1
    
                }
            },"t2");
            t1.start();
            t2.start();
        }
    }

    思路3:CAS自旋锁的思路,一个线程while死循环等待。

    public class test_cas {
        enum ReadToRun{T1,T2}
        static volatile  ReadToRun r = ReadToRun.T1;
    
        public static void main(String[] args) {
            char []aI = "123456789".toCharArray();
            char []aC = "ABCDEFJHI".toCharArray();
            new Thread(()->{
                for (char c : aI) {
                    while(r != ReadToRun.T2){
    
                    }
                    System.out.println(c);
                    r = ReadToRun.T1;
                }
            },"t1").start();
            new Thread(()->{
                for (char c : aC) {
                    while(r != ReadToRun.T1) {
    
                    }
                    System.out.println(c);
                    r = ReadToRun.T2;
                }
            },"t2").start();
        }

    思路4:sync锁  wait notify(注意wait notify顺序不能换)

    public class test_sync_wait_notify {
        public static void main(String[] args) {
            char []aI = "123456789".toCharArray();
            char []aC = "ABCDEFJHI".toCharArray();
            final  Object o = new Object();
    
            new Thread(()->{
                synchronized (o){
                    for (char c : aI) {
                        System.out.println(c);
                        try {
                            o.notify();//叫醒另外一个线程
                            o.wait();//让出锁
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    o.notify();//必须 否则无法停止程序
                }
            },"t1").start();
    
            new Thread(()->{
                synchronized (o){
                    for (char c : aC) {
                        System.out.println(c);
                        try {
                            o.notify();
                            o.wait();//让出锁
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    o.notify();//必须 否则无法停止程序
                }
            },"t2").start();
        }
    }

     可以用CountDownLatch控制先后。

    import java.util.concurrent.CountDownLatch;
    
    public class test_sync_wait_notify {
    
    
        private static CountDownLatch countDownLatch = new CountDownLatch(1);//控制两个线程先后
        public static void main(String[] args) {
            char []aI = "123456789".toCharArray();
            char []aC = "ABCDEFJHI".toCharArray();
            final  Object o = new Object();
    
            new Thread(()->{
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o){
                    for (char c : aC) {
                        System.out.println(c);
                        try {
                            o.notify();//叫醒另外一个线程
                            o.wait();//让出锁
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    o.notify();//必须 否则无法停止程序
                }
            },"t1").start();
    
            new Thread(()->{
                synchronized (o){
                    for (char c : aI) {
                        System.out.println(c);
                        countDownLatch.countDown();
                        try {
                            o.notify();
                            o.wait();//让出锁
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    o.notify();//必须 否则无法停止程序
    
                }
            },"t2").start();
        }
    }

    思路5:reentrantlock和condition实现。

    public class test_Lock_Condition {
        public static void main(String[] args) {
            char []aI = "123456789".toCharArray();
            char []aC = "ABCDEFJHI".toCharArray();
            Lock lock = new ReentrantLock();
            //condition是一个队列,有一个condition就有一个队列,好处是指定哪个队列唤醒
            Condition conditionT1 = lock.newCondition();
            Condition conditionT2 = lock.newCondition();
            new Thread(()->{
                try{
                    lock.lock();//锁住,相当于sync
                    for (char c : aI) {
                        System.out.println(c);
                        conditionT2.signal();//叫醒conditionT2队列的线程
                        conditionT1.await();
                    }
                    conditionT2.signal();
                }catch (Exception e){
                    e.printStackTrace();
                }
                finally {
                    lock.unlock();
                }
            },"t1").start();
    
            new Thread(()->{
                try{
                    lock.lock();
                    for (char c : aC) {
                        System.out.println(c);
                        conditionT1.signal();
                        conditionT2.await();
                    }
                    conditionT1.signal();
                }catch (Exception e){
                    e.printStackTrace();
                }
                finally {
                    lock.unlock();
                }
            },"t2").start();
        }
    }

         

  • 相关阅读:
    Docker常见应用部署(3)
    数据库 'FileServer' 的版本为 904,无法打开。此服务器支持 852 版及更低版本。不支持降级路径。 无法打开新数据库
    Dockerfile 构建镜像(4)
    DockerHub 镜像仓库(5)
    ASP.NET Core 6.0 中使用 Autofac
    ASP.NET Core 6.0 使用RabbitMQ
    安装node.js环境,构建第一个vue项目
    Chrome 搜索结果始终保持新标签打开
    最短路
    [转载] Open3D显示点云常见方式
  • 原文地址:https://www.cnblogs.com/Esquecer/p/12517220.html
Copyright © 2020-2023  润新知