三个线程循环的按顺序打印

问题是:启动3个线程顺序打印ABC 10次,不能使用sleep。

方案一:

public class ThreadDemo{

    public static void main(String[] args) {

        MyLock lock = new MyLock();

        Thread a = new Thread(new MyPrinter("A", "B", lock));
        Thread b = new Thread(new MyPrinter("B", "C", lock));
        Thread c = new Thread(new MyPrinter("C", "A", lock));

        a.start();
        b.start();
        c.start();

        lock.setHolder("A");
    }

    static class MyPrinter implements Runnable {

        private String myName;
        private String nextName;
        private final MyLock lock;

        public MyPrinter(String myName, String nextName, MyLock lock) {
            this.myName = myName;
            this.nextName = nextName;
            this.lock = lock;
        }

        public void run() {
            int count = 3;
            while (count > 0) {
                if (lock != null && lock.getHolder() != null && lock.getHolder().equals(myName)) {
                    synchronized (lock) {
                        System.out.print(myName);
                        count--;
                        lock.setHolder(nextName);
                    }
                }

            }
        }
    }

    static class MyLock {

        public MyLock() {
        }
        private String holder;

        public String getHolder() {
            return holder;
        }

        public void setHolder(String holder) {
            this.holder = holder;
        }
    }
}

方案二:

对上一个方案进行修改:把count定义为static,不然每个线程之间可没法共享count变量,且由于是输出后再--,故设置成9比较合适。

public class ThreadDemo{  
  
    public static void main(String[] args) {  
  
        MyLock lock = new MyLock();  
  
        Thread a = new Thread(new MyPrinter("A", "B", lock));  
        Thread b = new Thread(new MyPrinter("B", "C", lock));  
        Thread c = new Thread(new MyPrinter("C", "A", lock));  
  
        a.start();  
        b.start();  
        c.start();  
  
        lock.setHolder("A");  
    }  
  
    static class MyPrinter implements Runnable {  
  
        private String myName;  
        private String nextName;  
        private final MyLock lock; 
        static int count = 9;  
  
        public MyPrinter(String myName, String nextName, MyLock lock) {  
            this.myName = myName;  
            this.nextName = nextName;  
            this.lock = lock;  
        }  
  
        public void run() {  
            while (count > 0) {  
                if (lock != null && lock.getHolder() != null && lock.getHolder().equals(myName)) {  
                    synchronized (lock) {  
                        System.out.print(myName);  
                        count--;  
                        lock.setHolder(nextName);  
                    }  
                }  
  
            }  
        }  
    }  
  
    static class MyLock {  
  
        public MyLock() {  
        }  
        private String holder;  
  
        public String getHolder() {  
            return holder;  
        }  
  
        public void setHolder(String holder) {  
            this.holder = holder;  
        }  
    }  
} 

方案三:

本质应该是操作系统中的同步问题,设定好信号量,使用PV元语就可以。要用java实现的话,使用wait()和notify()应该就OK。

public class ThreadDemo {
	public static void main(String[] args) {
		final int count = 3;
		String[] abc = { "a", "b", "c" };
		for (int i = 0; i < abc.length; i++) {
			final String current = abc[i];
			final String next = abc[(i + 1) % abc.length];
			new Thread(new Runnable() {
				public void run() {
					for (int j = 0; j < count; j++) {
						synchronized (current) {
							// 等待信号
							try {
								current.wait();
							} catch (InterruptedException e) {
							}
							System.out.print(current);
							// 给下个线程发信号
							
							synchronized (next) {
								next.notify();
							}
						}
					}
				}
			}).start();
		}
		// 通给第一个线程发信号
		synchronized (abc[0]) {
			abc[0].notify();
		}
	}
}


可用用如下方式分析(参考)

public class ThreadDemo {
	public static void main(String[] args) {
		final int count = 3;
		String[] abc = { "a", "b", "c" };
		for (int i = 0; i < abc.length; i++) {
			final String current = abc[i];
			final String next = abc[(i + 1) % abc.length];
			new Thread(new Runnable() {
				public void run() {
					for (int j = 0; j < count; j++) {
						synchronized (current) {
							// 等待信号
							System.out.println(current + "等待信号");
							try {
								current.wait();
							} catch (InterruptedException e) {
							}
							System.out.println(current + "给下一个线程发信号");
							// 给下个线程发信号
							
							synchronized (next) {
								next.notify();
							}
						}
						System.out.println("第" + j + "次循环");
					}
				}
			}).start();
		}
		// 通给第一个线程发信号
		System.out.println("给第一个线程发信号");
		synchronized (abc[0]) {
			abc[0].notify();
		}
	}
}

方案四:

import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
 public class ThreadDemo {
     private static Lock lock = new ReentrantLock();//通过JDK5中的锁来保证线程的访问的互斥
     private static int state = 0;
     
     static class ThreadA extends Thread {
         @Override
         public void run() {
             for (int i = 0; i < 3;) {
                 lock.lock();
                 if (state % 3 == 0) {
                     System.out.print("A");
                     state++;
                     i++;
                 }
                 lock.unlock();
             }
         }
     }
     
     static class ThreadB extends Thread {
         @Override
         public void run() {
             for (int i = 0; i < 3;) {
                 lock.lock();
                 if (state % 3 == 1) {
                     System.out.print("B");
                     state++;
                     i++;
                 }
                 lock.unlock();
             }
         }
     }
     
     static class ThreadC extends Thread {
         @Override
         public void run() {
             for (int i = 0; i < 3;) {
                 lock.lock();
                 if (state % 3 == 2) {
                     System.out.print("C");
                     state++;
                     i++;
                 }
                 lock.unlock();
             }
         }
     }
     
     public static void main(String[] args) {
         new ThreadA().start();
         new ThreadB().start();
         new ThreadC().start();
     }
     
 }

方案五:

使用lock来保证只有一个线程在输出操作, 要保证了state不会被两个线程同时修改, 还可以使用condition, condition的效率可能会更高一些, await会释放lock锁, condition的await和signal与object的wait和notify方法作用类似

import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
 public class ThreadDemo {
     private static Lock lock = new ReentrantLock();
     private static int count = 0;
     private static Condition A = lock.newCondition();
     private static Condition B = lock.newCondition();
     private static Condition C = lock.newCondition();
     
     static class ThreadA extends Thread {
 
         @Override
         public void run() {
             lock.lock();
             try {
                 for (int i = 0; i < 3; i++) {
                     while (count % 3 != 0)
                         A.await(); // 会释放lock锁
                     System.out.print("A");
                     count++;
                     B.signal(); // 唤醒相应线程
                 }
             } catch (InterruptedException e) {
                 e.printStackTrace();
             } finally {
                 lock.unlock();
             }
         }
         
     }
     
     static class ThreadB extends Thread {
 
         @Override
         public void run() {
             lock.lock();
             try {
                 for (int i = 0; i < 10; i++) {
                     while (count % 3 != 1)
                         B.await();
                     System.out.print("B");
                     count++;
                     C.signal();
                 }
             } catch (InterruptedException e) {
                 e.printStackTrace();
             } finally {
                 lock.unlock();
             }
         }
         
     }
     
     static class ThreadC extends Thread {
 
         @Override
         public void run() {
             lock.lock();
             try {
                 for (int i = 0; i < 10; i++) {
                     while (count % 3 != 2)
                         C.await();
                     System.out.print("C");
                     count++;
                     A.signal();
                 }
             } catch (InterruptedException e) {
                 e.printStackTrace();
             } finally {
                 lock.unlock();
             }
         }
         
     }
     
     public static void main(String[] args) throws InterruptedException {
         new ThreadA().start();
         new ThreadB().start();
         ThreadC threadC = new ThreadC();
         threadC.start();
         threadC.join();
         System.out.println(count);
     }
 }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值