精华内容
下载资源
问答
  • 2020-10-31 15:11:20

    简介

    本文将承接文章《Java多线程wait()和notify()系列方法使用教程》,我们将通过“两个线程交替打印100内的奇偶数”,来展示下wait()方法和notify()方法的用法和优点,当然要体现出优点,自然要通过对比不使用这两个方法实现同一功能的代码,通过这几篇文章的讲解,帮你彻底搞懂wait()方法和notify()方法的用法。

    一.仅通过synchronized关键字实现交替打印奇偶数

    1.实现逻辑:

    创建两个线程,一个线程负责打印奇数,另一个线程打印偶数,两个线程竞争同一个对象锁,每次打印一个数字后释放锁,然后另一个线程拿到锁打印下一个数字。

    2.代码实现:

    public class PrintOddEven1 {
    	private static int count;
    
    	private static final Object object = new Object();
    
    	public static void main(String[] args) {
    		new Thread(new Runnable() {
    			@Override
    			public void run() {
    				while (count < 100) {
    					synchronized (object) {
    						if ((count & 1) == 0) {
    							System.out.println(Thread.currentThread().getName() + ":" + count++);
    						}
    					}
    				}
    
    			}
    		}, "偶数线程").start();
    
    		new Thread(new Runnable() {
    			@Override
    			public void run() {
    				while (count < 100) {
    					synchronized (object) {
    						if ((count & 1) == 1) {
    							System.out.println(Thread.currentThread().getName() + ":" + count++);
    						}
    					}
    				}
    
    			}
    		}, "奇数线程").start();
    	}
    
    }
    

    3.结果输出:

    偶数线程:0
    奇数线程:1
    偶数线程:2
    奇数线程:3
    偶数线程:4
    奇数线程:5
    偶数线程:6
    奇数线程:7
    偶数线程:8
    奇数线程:9
    偶数线程:10
    

    4.结果分析:

    通过创建两个线程,这两个线程共享object对象锁,当一个线程打印完一个数字后,会释放对象锁,另一个线程拿到对象锁,然后判断是否为偶数(奇数),满足条件则打印。

    二.通过synchronized关键字配合wait和notify方法实现交替打印奇偶数

    1.实现逻辑:

    无需判断数字是否是奇偶数,两个线程通过等待唤醒机制,交替打印数字。

    2.代码实现:

    public class PrintOddEven2 {
    
    	private static int count = 0;
    	private static final Object object = new Object();
    
    	public static void main(String[] args) {
    		new Thread(new printer(), "偶数线程,").start();
    		new Thread(new printer(), "奇数线程,").start();
    	}
    
    	static class printer implements Runnable {
    
    		@Override
    		public void run() {
    			while (count <= 100) {
    				synchronized (object) {
    					// 打印数字,并立即释放锁
    					System.out.println(Thread.currentThread().getName() + "打印:" + count++);
    					object.notify();
    					// 此处判断,是为了打印完了100个数字后,程序能够正常结束,否则程序将一直等待下去,耗费系统资源。
    					if (count <= 100) {
    						try {
    							object.wait();
    						} catch (InterruptedException e) {
    							e.printStackTrace();
    						}
    					}
    				}
    			}
    		}
    	}
    
    }
    
    
    

    3.结果输出:

    偶数线程,打印:0
    奇数线程,打印:1
    偶数线程,打印:2
    奇数线程,打印:3
    偶数线程,打印:4
    奇数线程,打印:5
    偶数线程,打印:6
    奇数线程,打印:7
    偶数线程,打印:8
    奇数线程,打印:9
    偶数线程,打印:10
    ……省略
    

    4.结果分析:

    此种方式,写法简洁,让线程拿到对象锁后,立即打印数字,然后通过notify()释放锁,然后调用wait()方法使线程进入等待状态。另一个线程拿到锁以后,也立即打印数字,然后通过notify()释放锁,然后进入等待状态。知道打印完100以内的所有数字,两个线程都能正常停止运行。

    总结

    本文作为wait()notify()方法的用法示例教程,展示wait()notify()方法的用法,下一篇文章将再展示一个wait()notify()方法的使用案例《设计模式之消费者生产者模式》,将带大家继续领悟下线程唤醒通知机制使用意义所在。

    建议收藏:

    关于synchronized关键字wait()notify()方法的系列教程,请参考以下文章:

    《Java中synchronized实现类锁的两种方式及原理解析》

    《Java中synchronized实现对象锁的两种方式及原理解析》

    《Java多线程wait()和notify()系列方法使用教程》

    《Java多线程中notifyAll()方法使用教程》

    《Java中Synchronized的可重入性和不可中断性的分析和代码验证》

    《Java多线程访问Synchronized同步方法的八种使用场景》

    《Java官方文档创建线程的两种方式及优点和缺点分析》

    《Java中线程安全和线程不安全解析和示例》

    更多相关内容
  • import java.util.concurrent.locks.Lock; import java.util.concurrent....* Function: 两个线程交替执行打印 1~100 * * lock 版 * */ public class TwoThread { private int start =...

    package com.lock.actual;

     

    import java.util.concurrent.locks.Lock;

     

    import java.util.concurrent.locks.ReentrantLock;

     

    /**

     

     * Function: 两个线程交替执行打印 1~100

     

     *

     

     * lock 版

     

     *

     

     */

     

    public class TwoThread {

     

        private int start = 1;

     

        /**

     

         * 对 flag 的写入虽然加锁保证了线程安全,但读取的时候由于 不是 volatile 所以可能会读取到旧值

     

         *

     

         */

     

        private volatile boolean flag = false;

     

        /**

     

         * 重入锁

     

         */

     

        private final static Lock LOCK = new ReentrantLock();

     

        public static void main(String[] args) {

     

            TwoThread twoThread = new TwoThread();

     

            Thread t1 = new Thread(new OuNum(twoThread));

     

            t1.setName("t1");

     

            Thread t2 = new Thread(new JiNum(twoThread));

     

            t2.setName("t2");

     

            t1.start();

     

            t2.start();

     

        }

     

        /**

     

         * 偶数线程

     

         */

     

        public static class OuNum implements Runnable {

     

            private TwoThread number;

     

            public OuNum(TwoThread number) {

     

                this.number = number;

     

            }

     

            @Override

     

            public void run() {

     

                while (number.start <= 1000) {

     

                    if (number.flag) {

     

                        try {

     

                            LOCK.lock();

     

                            System.out.println(Thread.currentThread().getName() + "+-+" + number.start);

     

                            number.start++;

     

                            number.flag = false;

     

                        } finally {

     

                            LOCK.unlock();

     

                        }

     

                    }

     

                }

     

            }

     

        }

     

        /**

     

         * 奇数线程

     

         */

     

        public static class JiNum implements Runnable {

     

            private TwoThread number;

     

            public JiNum(TwoThread number) {

     

                this.number = number;

     

            }

     

            @Override

     

            public void run() {

     

                while (number.start <= 1000) {

     

                    if (!number.flag) {

     

                        try {

     

                            LOCK.lock();

     

                            System.out.println(Thread.currentThread().getName() + "+-+" + number.start);

     

                            number.start++;

     

                            number.flag = true;

     

                        } finally {

     

                            LOCK.unlock();

     

                        }

     

                    }

     

                }

     

            }

     

        }

     

    }

    展开全文
  • 线程交替打印奇偶数涉及到的三个方法: 涉及到的三个方法: wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。 notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有个线程被wait,就...

    线程交替打印奇偶数

    涉及到的三个方法:

    • wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
    • notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个。
    • notifyAll():一旦执行此方法,就会唤醒所有被wait的线程。

    **** 说明:***
    1.wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中。
    2.wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器。否则,会出现IllegalMonitorStateException异常
    3.wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中。

    class Num1 implements Runnable {
        private Test1 ticket;
    
        public Num1(Test1 ticket) {
            this.ticket = ticket;
        }
        @Override
        public void run() {
            while (ticket.num>0) {
                synchronized (ticket) {
                    if(ticket.num%2==0){
                        try {
                            ticket.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else{
                        System.out.println(Thread.currentThread().getName()+":"+ticket.num);
                        ticket.num--;
                        ticket.notify();
                    }
                }
            }
        }
    }
    class Num2 implements Runnable {
        private Test1 ticket;
    
        public Num2(Test1 ticket) {
            this.ticket = ticket;
        }
        @Override
        public void run() {
            while (ticket.num>0) {
                synchronized (ticket) {
                    if(ticket.num%2!=0){
                        try {
                            ticket.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else{
                        System.out.println(Thread.currentThread().getName()+":"+ticket.num);
                        ticket.num--;
                        ticket.notify();
                    }
                }
            }
        }
    }
    public class Test1 {
        public int num=100;
    
        public static void main(String[] args) {
            Test1 ticket = new Test1();
            Num1 n1=new Num1(ticket);
            Thread t1=new Thread(n1);
            Num2 n2=new Num2(ticket);
            Thread t2=new Thread(n2);
            t1.setName("奇数项");
            t2.setName("偶数项");
            t1.start();
            t2.start();
    
        }
    }
    
    
    展开全文
  • 主要介绍了Java 实现多线程切换等待唤醒交替打印奇偶数 ,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 构造两个线程交替打印1-100之间的数字,其中线程1打印奇数,线程2打印偶数。 方式1:采用synchronized同步锁和wait,notify线程通信机制来实现。 public class jiaotidayinshuzi { public static void main...

    交替打印奇偶数

    问题描述:

    •  构造两个线程,交替打印1-100之间的数字,其中线程1打印奇数,线程2打印偶数。 
      

    方式1:采用synchronized同步锁和wait,notify线程通信机制来实现。

    public class jiaotidayinshuzi {
        public static void main(String[] args){
            PrintNum p=new PrintNum();
            Thread td1=new Thread(p);
            Thread td2=new Thread(p);
            td1.setName("线程1");
            td2.setName("线程2");
            td1.start();
            td2.start();
        }
    }
    //定义打印函数,通过wait()和notify()交替打印奇偶数
    class PrintNum implements Runnable{
        int num=1;
        @Override
        public void run() {
            synchronized (this){
                while (true){
                    notify();//唤醒wait()的一个或者所有的线程
                    if (num<=100){
                        System.out.println(Thread.currentThread().getName()+":"+num);
                        num++;
                    }else {
                        break;
                    }
                    try {
                        wait();//释放当前的锁,另一个线程就进来
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    

    方式2:采用标志位来实现交替打印

    将共享资源定义为类(counter),共享资源类中包含待打印的变量和标志位。

    public class jiaotidayinshuzi02 {
        public static void main(String[] args) {
            Counter counter=new Counter();
            new Thread(new PrintOdd(counter),"线程1(打印奇数)").start();
            new Thread(new PrintEven(counter),"线程2(打印偶数)").start();
        }
    }
    
    class Counter {
        public int value = 1;
        public boolean odd = true;
    }
    
    class PrintOdd implements Runnable {
        public Counter counter;
    
        public PrintOdd(Counter counter) {
            this.counter = counter;
        }
    
        @Override
        public void run() {
            while (counter.value <= 100) {
                synchronized (counter) {
                    if (counter.odd) {
                        System.out.println(Thread.currentThread().getName()+":"+counter.value);
                        counter.value++;
                        counter.odd = !counter.odd;
                        //唤醒打印偶数的线程
                        counter.notify();
                    }
                    try {
                        counter.wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
        }
    }
    class PrintEven implements Runnable{
        public  Counter counter;
    
        public PrintEven(Counter counter) {
            this.counter = counter;
        }
    
        @Override
        public void run() {
            while (counter.value<=100){
                synchronized (counter){
                    if(!counter.odd){
                        System.out.println(Thread.currentThread().getName()+":"+counter.value);
                        counter.value++;
                        counter.odd=!counter.odd;
                        counter.notify();
                    }
                    try {
                        counter.wait();
                    }catch (InterruptedException e){
                    }
                }
            }
        }
    }
    

    方式3:不加锁,采用while和boolean标识位来实现

    public class jiaotidayinshuzi03 {
        volatile static boolean open = true;
        volatile static int count = 1;
        static Thread td1 = new Thread(new PrintOdd(), "线程1(打印奇数)");
        static Thread td2 = new Thread(new PrintEven(), "线程2(打印偶数)");
        public static void main(String[] args) {
            td1.start();
            td2.start();
        }
        //定义打印奇数的类,实现Runnable接口,重写run()方法。静态内部类
        static class PrintOdd implements Runnable {
    
            @Override
            public void run() {
                while (count <= 100) {
                    //通过标志位open来判断是否执行打印函数
                    if (open) {
                        System.out.println(Thread.currentThread().getName() + ":" + count);
                        count++;
                        //执行完打印过程后变更标志位
                        open = false;
                    }
                }
            }
        }
        //定义打印偶数的类,实现Runnable接口,重写run()方法
        static class PrintEven implements Runnable {
    
            @Override
            public void run() {
                while (count <= 100) {
                    if (!open) {
                        System.out.println(Thread.currentThread().getName() + ":" + count);
                        count++;
                        open = true;
                    }
                }
            }
        }
    }
    
    
    
    展开全文
  • * Description: 使用等待唤醒机制打印奇数偶数 -- while循环的方式 * 注意: * 1.必须指明是object对象在调用notify和wait方法,不指明默认就是this-当前对象(那你代码肯定跑不起来) (i)我们锁的对象是...
  • 多线程:两个线程交替打印奇偶数

    千次阅读 2018-08-22 14:17:35
    要求:两个线程交替打印从1到100的数字。
  • 设计两个线程打印1-10,一个线程打印奇数,另一个线程打印偶数,要求交替打印。 最后输出123……10 方法一(Synchronized+共享变量) 1.解题思路 新建一个对象,并定义一个共享变量。只要flag不为1,线程t2就会阻塞...
  • 关于ReentrantLock的实现原理,详见这篇:...为什么要用ReentrantLock呢,因为这里交替打印线程交替执行),需要对共享变量flag进行反复...
  • 思路:利用Object.wait()和Object.notify()方法进行线程间的通信。 代码: public class MyThread implements Runnable { private static int i = 1; private byte[] s1; public MyThread(byte[] s1) { ...
  • 需要使用两个线程交替打印奇偶数。使用同步锁解决这个问题使用信号量来实现交替打印定义两个信号量,一个奇数信号量,一个偶数信号量,都初始化为1先用掉偶数的信号量,因为要让奇数先启动,等奇数打印完再释放信号...
  • 两个线程交替打印奇偶数的问题
  • 引言java面试中经常会遇到这个问题,如何用两个线程交替打印奇偶数。线程A打印1,线程B打印2,线程A打印3,线程B打印4...这个问题的解题思路是协调两个线程的执行时机,线程A与线程B需要交替执行。实现的方式很,...
  • 两个线程都持有相同的一个信号量,奇数线程启动,获取信号量,然后打印完,释放信号量,再休眠,然后偶数线程启动,获取信号量,然后打印完,释放信号量 package demo6; import java.util.concurrent.Semaphore; /...
  • #include<iostream> #include<mutex> #include<thread> #include<condition_variable> #include<Windows.h> using namespace std;...//线程1 void thread1() { while (1) { un
  • 里面提到了:两个线程交替打印奇偶数这道笔试题。update on 2020/6/7,下面的第二种方式,现在回头看,其实感觉写得不好,下面直接贴一种更直接的方式(目前的技术水平写的,应该比之前的写的好点)。1 @Slf4j2 ...
  • 实现思想主要是让两个线程互相唤醒对方来交替打印数字 #include <unistd.h> #include <stdlib.h> #include <pthread.h> #include <stdio.h> int g_num = 1; pthread_mutex_t mutex; ...
  • 使用C++11标准的的线程语法,用两个线程轮流打印整数,一个线程打印奇数,一个线程打印偶数。可以练习线程的基本操作、线程锁和条件变量等技术。完整代码如下。代码后面附有主要语句的讲解。 #include #include #...
  • JDK1.8新特性, 多线程交替打印奇偶数 package demo; import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; /** * @ClassName 交替打印奇偶数 * @Description 这里描述 * @Author admin * @Date 2021/3/16 ...
  • lockb.release() time.sleep(0.2) if __name__ == '__main__': # 定义两个互斥锁 locka = threading.Lock() lockb = threading.Lock() # 定义两个线程 t1 = threading.Thread(target=printJ) t2 = threading.Thread...
  • 你给我写一下,起两个线程交替打印0~100的奇偶数。 小黄:啊? 面试官:就是有两个线程,一个线程打印奇数另一个打印偶数,它们交替输出。类似这样 偶线程:0 线程:1 偶线程:2 …… 线程:99 偶线程:100 小...
  • 如何利用多线程交替输出奇偶数

    千次阅读 2020-02-13 16:10:43
    如何利用多线程交替输出奇偶数 更多干货见博主个人网站:https://blog.zhenglin.work 用两个线程分别输出奇数、偶数 思路:两个线程,一个输出奇数,一个输出偶数;说明这两个线程公用一个数据池。一个线程输出...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,251
精华内容 900
关键字:

多线程交替打印奇偶数