两个线程交替打印1到100

交替打印偶数与奇数线程示例
本文提供了一个使用Java实现的线程示例,通过两个线程交替打印1到100之间的奇数和偶数。该示例展示了如何利用synchronized关键字、wait()与notify()方法来实现线程间的同步与通信。
package com.zs.thread;

import java.util.concurrent.TimeUnit;

public class SumThread {
    
    public void one() throws InterruptedException{
        synchronized (this) {
            boolean flag = true;
            
            while (flag) {
                
                for(int i = 1; i <= 99;i += 2){
                    System.out.println(i);
                    
                    if(i==99){
                        flag = false;
                        this.notify();
                        break;
                    }
                    this.notify();
                    this.wait();
                }
            }
        }
    }   
        
    public void two() throws InterruptedException{
            synchronized (this) {
                boolean flag = true;
                
                while (flag) {
                    
                    for(int i = 2; i <= 100;i += 2){
                        System.out.println(i);
                        
                        if(i==100){
                            flag = false;
                            this.notify();
                            break;
                        }
                        this.notify();
                        this.wait();
                    }
                }
            }
        }
        
        
    
    public static void main(String[] args) throws Exception {
        SumThread sumThread = new SumThread();
        
        new Thread(()->{
            try {
                sumThread.one();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        
        TimeUnit.SECONDS.sleep(1);
        
        new Thread(()->{
            try {
                sumThread.two();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }
}

转载于:https://www.cnblogs.com/leihuazhe/p/7898563.html

<think>好的,我需要帮助用户找到用Java实现两个线程交替打印1100的代码示例。用户之前提到的相关引用里,有几个不同的方法,比如使用synchronized加锁、wait/notify机制,还有可能的Semaphore等工具。首先,我应该回顾用户提供的引用内容,看看哪些方法适合这个问题。 引用[1]中提到了使用递加取余判断,不加锁的方式,但可能涉及竞争条件,不太可靠。引用[2]和[3]、[4]都使用了synchronized结合wait和notify,这种方法比较经典,可以确保线程交替执行。引用[5]提到了使用并发工具如Semaphore,但用户可能更倾向于简单直接的实现。 用户的需求是两个线程交替打印1100,所以每个线程负责打印一个数字,然后轮到另一个线程。关键点在于线程间的同步,确保每次只有一个线程执行打印,并且正确切换。使用synchronized和wait/notify机制是常见的方法,如引用[3]中的例子,但需要调整计数器初始值和判断条件。 在引用[3]的代码中,两个线程交替打印奇偶数,初始值为0,但用户需要从1开始到100。因此需要修改计数器初始值为1,并调整判断条件。或者,可能需要在代码中让一个线程处理奇数,另一个处理偶数,但用户的问题是两个线程交替打印,可能不需要区分奇偶,而是严格交替,每次加1。 另一个考虑是,使用共享的锁对象和计数器,每个线程在获得锁后检查是否应该自己执行打印。比如,线程1打印当前数字,然后唤醒另一个线程,自己等待。线程2被唤醒后,检查条件,打印下一个数字,依此类推。 需要注意的是,在wait/notify机制中,必须使用while循环来防止虚假唤醒。例如,当线程被唤醒后,需要再次检查条件是否满足,否则可能产生错误。 根据引用[3]的示例,可以调整计数器从1开始,并在每次打印后递增。线程A负责在计数器为奇数时打印线程B在偶数时打印,或者反过来。或者,可能不需要判断奇偶,而是通过一个标志变量来控制交替。但这样会增加复杂度,而使用奇偶判断可能更简单。 例如,一个线程处理奇数,另一个处理偶数。但用户的问题只需要两个线程交替打印,不管奇偶,所以更准确的方式可能是线程1打印数字,然后线程2打印下一个,依此类推。这种情况下,可能需要一个变量来指示当前轮到哪个线程执行。 不过,根据引用[3]的例子,即使不区分奇偶,而是通过wait/notify让线程交替执行。例如,当计数器递增后,唤醒另一个线程,自己等待。这样,每个线程打印后唤醒对方,自己进入等待状态。但需要确保初始状态下,一个线程先执行。 比如,设置初始值为1线程A先打印,然后递增到2,唤醒线程B,自己等待。线程B获得锁后,检查值是否满足条件(比如是否是偶数),然后打印,递增,唤醒线程A,依此类推,直到达到100。 或者,不判断奇偶,而是通过轮流的方式。例如,两个线程交替获取锁,但这种方式可能需要额外的标记变量。可能更简单的还是基于计数器的奇偶性来判断该哪个线程执行。 现在,综合这些考虑,我需要编写一个使用synchronized、wait和notify的代码,两个线程交替打印1100。其中一个线程负责奇数,另一个负责偶数。或者,让两个线程通过交替唤醒对方来实现。 例如,线程1打印1,然后唤醒线程2,自己等待。线程2打印2,唤醒线程1,依此类推。这样,每个线程打印后唤醒另一个线程,并等待,直到被唤醒。这种情况下,计数器不需要奇偶判断,而是由线程交替执行。不过,这种情况下需要确保初始启动时,一个线程先执行。 或者,可能使用一个boolean变量来标志该哪个线程执行。例如,当flag为true时,线程A执行,否则线程B执行。但需要结合wait/notify机制。 不过,根据用户提供的引用[3],他们的代码通过判断奇偶,并且不需要额外的flag,而是通过计数器的奇偶性来决定哪个线程打印。这样可能更简洁,因为计数器本身的值已经包含所需的信息。 例如,计数器初始为1线程A在计数器为奇数时打印,递增到2,然后唤醒线程B;线程B在计数器为偶数时打印,递增到3,唤醒线程A,依此类推,直到达到100。 这样,两个线程通过检查计数器的奇偶性来决定是否执行打印。当线程获得锁时,如果当前计数器的值符合自己的条件(奇数或偶数),则打印并递增,然后唤醒另一个线程;否则,进入等待状态。 但需要考虑,当计数器超过100时,线程需要终止循环。因此,在循环条件中需要检查计数器是否<=100。 现在,编写具体的代码: 1. 定义一个共享的计数器count,初始值为12. 定义一个锁对象,比如Object lock = new Object(); 3. 创建两个线程,一个处理奇数,另一个处理偶数。 4. 每个线程在同步块中检查count是否<=100,如果是,判断是否应该自己打印(比如线程A处理奇数,线程B处理偶数)。 5. 打印后递增count,然后唤醒另一个线程,自己进入等待。 但是,这里可能存在问题,比如当count递增后,另一个线程被唤醒,但此时count可能已经超过了100,所以需要在循环条件中严格检查。或者在每次进入循环时检查count是否超过100。 例如: public class AlternatePrinting { private static int count = 1; private static final Object lock = new Object(); public static void main(String[] args) { Thread t1 = new Thread(() -> { while (count <= 100) { synchronized (lock) { if (count % 2 == 1) { // 奇数,由t1打印 System.out.println(Thread.currentThread().getName() + ": " + count); count++; lock.notify(); } else { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }); Thread t2 = new Thread(() -> { while (count <= 100) { synchronized (lock) { if (count % 2 == 0) { // 偶数,由t2打印 System.out.println(Thread.currentThread().getName() + ": " + count); count++; lock.notify(); } else { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }); t1.start(); t2.start(); } } 但是这样的代码可能存在一个问题:当count超过100后,线程可能仍然在循环中,因为循环条件是while (count <=100),但可能在进入循环后,count已经被另一个线程修改超过100,导致打印错误。例如,当count=100时,线程t2进入循环,此时count<=100为true。然后进入synchronized块,此时可能count已经被t1修改到101,导致线程t2的if条件不成立,进入wait,但此时没有其他线程来唤醒它,导致线程无法退出。 因此,需要在线程内部的循环中,在进入synchronized块之后再次检查count是否超过100,否则可能会在最后一次循环中导致问题。或者,在synchronized块内部,处理完打印后,立即检查是否应该退出循环。 修改代码,将循环条件放在synchronized块内部: 例如: public class AlternatePrinting { private static int count = 1; private static final Object lock = new Object(); public static void main(String[] args) { Thread t1 = new Thread(() -> { while (true) { synchronized (lock) { if (count > 100) { break; } if (count % 2 == 1) { System.out.println(Thread.currentThread().getName() + ": " + count); count++; lock.notify(); } else { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }); Thread t2 = new Thread(() -> { while (true) { synchronized (lock) { if (count > 100) { break; } if (count % 2 == 0) { System.out.println(Thread.currentThread().getName() + ": " + count); count++; lock.notify(); } else { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }); t1.start(); t2.start(); } } 这样,在每次进入synchronized块后,首先检查count是否超过100,如果是,则break退出循环。这可以防止在最后一次循环中打印超过100的数字。 此外,当count达到100时,某个线程打印后递增到101,另一个线程在进入synchronized块后检查到count>100,立即break,退出循环。这样就能正确终止。 另外,需要确保在最后一个数字打印后,两个线程都能正确退出。例如,当count=100时,如果由线程t2(处理偶数)打印,则count变为101,然后notify唤醒另一个线程t1线程t1进入synchronized块,发现count>100,break退出。线程t2打印后,退出循环。这样两个线程都能正确结束。 测试一下这个逻辑: 假设count=99,线程t1进入,判断count<=100,然后count是99,奇数,打印99,count变为100,notify唤醒t2。然后t1再次进入循环,进入synchronized块,检查count=100,未超过100。此时,count%2==0,所以t1进入else,调用wait,释放锁。t2获得锁,检查count=100,未超过,count%2==0,所以打印100,count变为101,notify唤醒t1。然后t2退出循环。t1被唤醒后,再次进入循环,进入synchronized块,检查count>100,break退出。这样两个线程都能正确结束。 因此,这个代码应该是可行的。 此外,用户提供的引用[3]中的代码也采用了类似的结构,在每次循环时检查count是否超过限制,并且在打印后立即notify,然后通过wait让出锁。这样确保了线程交替执行。 因此,最终的代码应该类似于上述结构,使用synchronized、wait和notify,并通过检查count是否超过100来正确终止线程。</think>以下是使用Java实现两个线程交替打印1100的代码示例。该方法基于`synchronized`同步机制和`wait/notify`线程通信,确保交替执行。 ### 代码实现 ```java public class AlternatePrinting { private static int count = 1; private static final Object lock = new Object(); public static void main(String[] args) { Thread threadA = new Thread(() -> { while (true) { synchronized (lock) { if (count > 100) break; if (count % 2 == 1) { // 奇数由线程A打印 System.out.println("线程A: " + count); count++; lock.notify(); // 唤醒线程B } else { try { lock.wait(); // 释放锁,等待唤醒 } catch (InterruptedException e) { e.printStackTrace(); } } } } }); Thread threadB = new Thread(() -> { while (true) { synchronized (lock) { if (count > 100) break; if (count % 2 == 0) { // 偶数由线程B打印 System.out.println("线程B: " + count); count++; lock.notify(); // 唤醒线程A } else { try { lock.wait(); // 释放锁,等待唤醒 } catch (InterruptedException e) { e.printStackTrace(); } } } } }); threadA.start(); threadB.start(); } } ``` ### 实现原理 1. **共享变量与锁**: - `count`为共享计数器,初始值为1。 - `lock`为同步锁对象,确保线程互斥访问共享资源。 2. **交替逻辑**: - 线程A负责打印奇数(`count % 2 == 1`),线程B负责打印偶数(`count % 2 == 0`)。 - 每个线程打印后调用`lock.notify()`唤醒对方线程,并调用`lock.wait()`释放锁,进入等待状态。 3. **终止条件**: - 每次获取锁后优先检查`count > 100`,若满足则退出循环,避免无效操作[^3]。 ### 注意事项 - **虚假唤醒**:`wait()`需在循环中调用,但此处通过`count`的严格检查已规避此问题。 - **执行顺序**:线程启动顺序不影响最终结果,因为首次执行时必有一个线程满足条件(`count=1`为奇数,线程A优先执行)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值