首页 > 作文

Java五种方式实现多线程循环打印问题

更新时间:2023-04-04 02:51:10 阅读: 评论:0

目录
wait-notify join方式 reentrantlock reentrantlock+condition maphore

三个线程t1、t2、t3轮流打印abc,打印n次,如abcabcabcabc…
n个线程循环打印1-100…

wait-notify

循环打印问题可以通过设置目标值,每个线程想打印目标值,如果拿到锁后这次轮到的数不是它想要的就进入wait

class wait_notify_abc {    private int num;    private static final object lock = new object();    private void print_abc(int target) {        synchronized (lock) {            //循环打印            for (int i = 0; i < 10; i++) {                while (num % 3 != target) {                    try {                        lock.wait();                    } catch (interruptedexception e) {                        e.printstacktrace();                    }                }                num++;                system.out.print(thread.currentthread().getname());                lock时事点评.notifyall();            }        }    }    public static void main(string[] args) {        wait_notify_abc wait_notify_abc = new wait_notify_abc();        new thread(() -> {            wait_notify_abc.print_abc(0);        }, "a").start();        new thread(() -> {            wait_notify_abc.print_abc(1);        }, "b").start();        new thread(() -> {            wait_notify_abc.print_abc(2);        }, "c").start();    }}

打印1-100问题可以理解为有个全局计数器记录当前打印到了哪个数,其它就和循环打印abc问题相同。

class wait_notify_100 {    private int num;    private static final object lock = new object();    private int maxnum = 100;    private void printabc(int targetnum) {        while (true) {            synchronized (lock) {                while (num % 3 != targetnum) {                    if (num >= maxnube元素m) {                        break;                    }                    try {                        lock.wait();                    } catch (interruptedexception e) {                        e.printstacktrace();                    }                }                if (num >= maxnum) {                    break;                }                num++;                system.out.println(thread.currentthread().getname() + ": " + num);                lock.notifyall();            }        }    }    public static void main(string[] args) {        wait_notify_100 wait_notify_100 = new wait_notify_100();        new thread(() -> {            wait_notify_100.printabc(0);        }, "thread1").start();        new thread(() -> {            wait_notify_100.printabc(1);        }, "thread2").start();        new thread(() -> {            wait_notify_100.printabc(2);        }, "thread3").start();    }}

join方式

一个线程内调用另一个线程的join()方法可以让另一个线程插队执行,比如main方法里调用了a.join(),那么此时cpu会去执行a线程中的任务,执行完后再看main是否能抢到运行权。所以对于abc,我们可以对b说让a插队,对c说让b插队

class join_abc {    static class printabc implements runnable {        private thread beforethread;        public printabc(thread beforethread) {            this.beforethread = beforethread;        }        @override        public void run() {            if (beforethread != null) {                try {                    beforethread.join();                } catch (interruptedexception e) {                    e.printstacktrace();                }            }            system.out.print(thread.currentthread().getname());        }    }    public static void main(string[] args) throws interruptedexception {        for (int i = 0; i < 10; i++) {            thread t1 = new thread(new printabc(null), "a");            thread t2 = new thread(new printabc(t1), "b");            thread t3 = new thread(new printabc(t2), "c");            t1.start();            t2.start();            t3.start();            thread.sleep(100);        }    }}

reentrantlock

同理,synchronized和reentrantlock都是我们常用的加锁方式,不过后者可以中断,可以实现公平锁,可以使用condition…但是需要我们手动释放锁。jdk8后二者性能差不多,毕竟synchronized有锁升级的过程嘛。

class reentrantlock_abc {    private int num;       private lock lock = new reentrantlock();    private void printabc(int targetnum) {        for (int i = 0; i < 100; ) {            lock.lock();            if (num % 3 == targetnum) {                num++;                i++;                system.out.print(thread.currentthread().getname());            }            lock.unlock();        }    }    public static void main(string[] args) {        lock_abc lockabc = new lock_abc();        new thread(() -> {            lockabc.printabc(0);        }, "a").start();        new thread(() -> {            lockabc.printabc(1);        }, "b").start();        new thread(() -> {            lockabc.printabc(2);        }, "c").start();    }}

reentrantlock+condition

以上方式如果线程抢到锁后发现自己无法执行任务,那么就释放,然后别的线程再抢占再看是不是自己的…这种方式比较耗时,如果我们能实现精准唤醒锁呢,即a完成任务后唤醒它的下一个即b,这就用到我们的condition啦

class reentrantlock_condition_abc {    private int num;    private static lock lock = new reentrantlock();    private static condition c1 = lock.newcondition();    private static condition c2 = lock.newcondition();    private static condition c3 = lock.newcondition();    private void printabc(int targetnum, condition currentthread, condition nextthread) {        for (int i = 0; i < 100; ) {            lock.lock();            try {                while (num % 3 != targetnum) {                    currentthread.await();  //阻塞当前线程                }                num++;                i++;                system.out.print(thread.currentthread().getname());                nextthread.signal();    //唤醒下一个线程            } catch (exception e) {                e.printstacktrace();            } finally {                lock.unlock();            }        }    }    public static void main(string[] args) {        reentrantlock_condition_abc reentrantlockconditionabc = new 春天的图片景色画reentrantlock_condition_abc();        new thread(() -> {            reentrantlockconditionabc.printabc(0, c1, c2);        }, "a").start();        new thread(() -> {           信件格式模板 reentrantlockconditionabc.printabc(1, c2, c3);        }, "b").start();        new thread(() -> {            reentrantlockconditionabc.printabc病毒是不是生物(2, c3, c1);        }, "c").start();    }}

maphore

小伙伴们有没有想到过,在生产者消费者模型中我们有哪几种实现方式呢?wait\notify,reentrantlock,maphone,阻塞队列,管道输入输出流。
对的就是maphone。
maphore有acquire方法和relea方法。 当调用acquire方法时线程就会被阻塞,直到获得许可证为止。 当调用relea方法时将向maphore中添加一个许可证。如果没有获取许可证的线程, maphore只是记录许可证的可用数量。
使用maphore也可以实现精准唤醒。

class maphoreabc {    private static maphore s1 = new maphore(1); //因为先执行线程a,所以这里设s1的计数器为1    private static maphore s2 = new maphore(0);    private static maphore s3 = new maphore(0);    private void printabc(maphore currentthread, maphore nextthread) {        for (int i = 0; i < 10; i++) {            try {                currentthread.acquire();       //阻塞当前线程,即信号量的计数器减1为0                system.out.print(thread.currentthread().getname());                nextthread.relea();          //唤醒下一个线程,即信号量的计数器加1            } catch (interruptedexception e) {                e.printstacktrace();            }        }    }    public static void main(string[] args) throws interruptedexception {        maphoreabc printer = new maphoreabc();        new thread(() -> {            printer.printabc(s1, s2);        }, "a").start();        thread.sleep(100);        new thread(() -> {            printer.printabc(s2, s3);        }, "b").start();        thread.sleep(100);        new thread(() -> {            printer.printabc(s3, s1);        }, "c").start();    }}

到此这篇关于java五种方式实现多线程循环打印问题的文章就介绍到这了,更多相关java 多线程循环打印内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 02:51:09,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/2378688ff669b4ed2fb428357442bc0e.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:Java五种方式实现多线程循环打印问题.doc

本文 PDF 下载地址:Java五种方式实现多线程循环打印问题.pdf

标签:线程   方式   方法   计数器
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图