- 浏览: 465955 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
ty1972873004:
sunwang810812 写道我运行了这个例子,怎么结果是这 ...
Java并发编程: 使用Semaphore限制资源并发访问的线程数 -
lgh1992314:
simpleDean 写道请问,Logger.setLevel ...
Java内置Logger详解 -
sunwang810812:
我运行了这个例子,怎么结果是这样的:2号车泊车6号车泊车5号车 ...
Java并发编程: 使用Semaphore限制资源并发访问的线程数 -
jp260715007:
nanjiwubing123 写道参考你的用法,用如下方式实现 ...
面试题--三个线程循环打印ABC10次的几种解决方法 -
cb_0312:
SurnameDictionary文章我没看完,现在懂了
中文排序
最近发现公司有份笔试试卷中有道多线程的题目:有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC…
这个最早好像是迅雷的面试题目吧,看到了然后就想重温一下这个题目的解决方法。
在本文中,给出了五种这个题目的解决方法:
下面依次给出每种解决方案的代码:
使用sleep
使用synchronized, wait和notifyAll
JDK 1.5 引入J.U.C包之后,也给我们提供了更多实现多线程程序的选择: Condition, 原子类AtomicInteger以及Semaphore等。
使用Lock 和 Condition
使用Semaphore
使用AtomicInteger
转载请注明出处http://mouselearnjava.iteye.com/blog/1949228
AtomicInteger版本的实现有问题,有时可以实现ABC打印10次,有的情况下最后一次只能打印出A 或AB。
atoIntgeger.getAndIncrement(); 能保证线程安全箱,但是几个语句组合起来,无法保证线程安全的。
这个最早好像是迅雷的面试题目吧,看到了然后就想重温一下这个题目的解决方法。
在本文中,给出了五种这个题目的解决方法:
- 使用sleep
- 使用synchronized, wait和notifyAll
- 使用Lock 和 Condition
- 使用Semaphore
- 使用AtomicInteger
下面依次给出每种解决方案的代码:
使用sleep
package my.thread.test; /** * @author Eric */ public class SleepExample extends Thread { private static int currentCount = 0; public SleepExample(String name) { this.setName(name); } @Override public void run() { while (currentCount < 30) { switch (currentCount % 3) { case 0: if ("A".equals(getName())) { printAndIncrease(); } break; case 1: if ("B".equals(getName())) { printAndIncrease(); } break; case 2: if ("C".equals(getName())) { printAndIncrease(); } break; } } } private void printAndIncrease() { print(); increase(); } private void print() { System.out.println(getName()); if ("C".equals(getName())) { System.out.println(); } } private void increase() { currentCount++; } public static void main(String[] args) { new SleepExample("A").start(); new SleepExample("B").start(); new SleepExample("C").start(); } }
使用synchronized, wait和notifyAll
package my.thread.test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class PrintThreadExample { public static void main(String[] args) { PrintThreadExample example = new PrintThreadExample(); LetterPrinter letterPrinter = example.new LetterPrinter(); ExecutorService service = Executors.newFixedThreadPool(3); service.execute(example.new PrintRunnable(letterPrinter, 'A')); service.execute(example.new PrintRunnable(letterPrinter, 'B')); service.execute(example.new PrintRunnable(letterPrinter, 'C')); service.shutdown(); } private class LetterPrinter { private char letter = 'A'; public void print() { System.out.println(letter); if ('C' == letter) { System.out.println(); } } public void nextLetter() { switch (letter) { case 'A': letter = 'B'; break; case 'B': letter = 'C'; break; case 'C': letter = 'A'; break; } } /** * @return the letter */ public char getLetter() { return letter; } } private class PrintRunnable implements Runnable { private LetterPrinter letterPrinter = null; private char letter = ' '; /** * @param letterPrinter * @param letter */ public PrintRunnable(LetterPrinter letterPrinter, char letter) { super(); this.letterPrinter = letterPrinter; this.letter = letter; } public void run() { for (int i = 0; i < 10; i++) { synchronized (letterPrinter) { while (letter != letterPrinter.getLetter()) { try { letterPrinter.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } letterPrinter.print(); letterPrinter.nextLetter(); letterPrinter.notifyAll(); } } } } }
JDK 1.5 引入J.U.C包之后,也给我们提供了更多实现多线程程序的选择: Condition, 原子类AtomicInteger以及Semaphore等。
使用Lock 和 Condition
package my.thread.test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Logger; /** * 题目:有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC… * * 本程序采用Lock和Condition来实现。 * * @author Eric * */ public class ConditionExample { private Lock lock = new ReentrantLock(); private Condition conditionA = lock.newCondition(); private Condition conditionB = lock.newCondition(); private Condition conditionC = lock.newCondition(); /** 当前线程的名字 */ private char currentThreadName = 'A'; private static final Logger logger = Logger .getLogger("my.thread.test.OrderPrintTest"); public static void main(String[] args) { ConditionExample ce = new ConditionExample(); ExecutorService service = Executors.newFixedThreadPool(3); service.execute(ce.new ThreadA()); service.execute(ce.new ThreadB()); service.execute(ce.new ThreadC()); service.shutdown(); } private class ThreadA implements Runnable { public void run() { for (int i = 0; i < 10; i++) { lock.lock(); try { while (currentThreadName != 'A') { try { /* * 如果当前线程名字不是A,那么ThreadA就处理等待状态 */ conditionA.await(); } catch (InterruptedException e) { logger.severe(e.getLocalizedMessage()); } } /* * 打印出第几遍以及A信息 */ System.out.println(String.format("第%d遍", i + 1)); System.out.println("A"); /* * 将当前线程名置为B, 然后通知ThreadB执行 */ currentThreadName = 'B'; conditionB.signal(); } finally { lock.unlock(); } } } } private class ThreadB implements Runnable { public void run() { for (int i = 0; i < 10; i++) { lock.lock(); try { while (currentThreadName != 'B') { try { /* * 如果当前线程名字不是B,那么ThreadB就处理等待状态 */ conditionB.await(); } catch (InterruptedException e) { logger.severe(e.getLocalizedMessage()); } } /* * 打印信息B */ System.out.println("B"); /* * 将当前线程值置为C 并通过ThreadC来执行 */ currentThreadName = 'C'; conditionC.signal(); } finally { lock.unlock(); } } } } private class ThreadC implements Runnable { public void run() { for (int i = 0; i < 10; i++) { lock.lock(); try { while (currentThreadName != 'C') { try { /* * 如果当前线程名字不是C,那么ThreadC就处理等待状态 */ conditionC.await(); } catch (InterruptedException e) { logger.severe(e.getLocalizedMessage()); } } /* * 打印信息C */ System.out.println("C"); System.out.println(); /* * 将当前线程值置为A 并通过ThreadA来执行 */ currentThreadName = 'A'; conditionA.signal(); } finally { lock.unlock(); } } } } }
使用Semaphore
package my.thread.test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; public class SemaphoresExample { private Semaphore semaphoresA = new Semaphore(1); private Semaphore semaphoresB = new Semaphore(0); private Semaphore semaphoresC = new Semaphore(0); public static void main(String[] args) { SemaphoresExample example = new SemaphoresExample(); ExecutorService service = Executors.newFixedThreadPool(3); service.execute(example.new RunnableA()); service.execute(example.new RunnableB()); service.execute(example.new RunnableC()); service.shutdown(); } private class RunnableA implements Runnable { public void run() { for (int i = 0; i < 10; i++) { try { semaphoresA.acquire(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(String.format("第%d遍", i + 1)); System.out.println("A"); semaphoresB.release(); } } } private class RunnableB implements Runnable { public void run() { for (int i = 0; i < 10; i++) { try { semaphoresB.acquire(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("B"); semaphoresC.release(); } } } private class RunnableC implements Runnable { public void run() { for (int i = 0; i < 10; i++) { try { semaphoresC.acquire(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("C"); System.out.println(); semaphoresA.release(); } } } }
使用AtomicInteger
package my.thread.test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerExample { private AtomicInteger sycValue = new AtomicInteger(0); private static final int MAX_SYC_VALUE = 3 * 10; public static void main(String[] args) { AtomicIntegerExample example = new AtomicIntegerExample(); ExecutorService service = Executors.newFixedThreadPool(3); service.execute(example.new RunnableA()); service.execute(example.new RunnableB()); service.execute(example.new RunnableC()); service.shutdown(); } private class RunnableA implements Runnable { public void run() { while (sycValue.get() < MAX_SYC_VALUE) { if (sycValue.get() % 3 == 0) { System.out.println(String.format("第%d遍", sycValue.get() / 3 + 1)); System.out.println("A"); sycValue.getAndIncrement(); } } } } private class RunnableB implements Runnable { public void run() { while (sycValue.get() < MAX_SYC_VALUE) { if (sycValue.get() % 3 == 1) { System.out.println("B"); sycValue.getAndIncrement(); } } } } private class RunnableC implements Runnable { public void run() { while (sycValue.get() < MAX_SYC_VALUE) { if (sycValue.get() % 3 == 2) { System.out.println("C"); System.out.println(); sycValue.getAndIncrement(); } } } } }
转载请注明出处http://mouselearnjava.iteye.com/blog/1949228
评论
3 楼
jp260715007
2016-06-30
nanjiwubing123 写道
参考你的用法,用如下方式实现。
@Slf4j public class TestUtil { private static AtomicInteger atoIntgeger = new AtomicInteger(0); public static void multPrint(){ ExecutorService excExecutorService = Executors.newFixedThreadPool(3); Future<Boolean> aFuture = excExecutorService.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { if(atoIntgeger.get() % 3 ==0){ atoIntgeger.getAndIncrement(); System.out.println("A"); } return true; } }); Future<Boolean> bFuture = excExecutorService.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { if(atoIntgeger.get() % 3 ==1){ atoIntgeger.getAndIncrement(); System.out.println("B"); } return true; } }); Future<Boolean> cFuture = excExecutorService.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { if(atoIntgeger.get() % 3 ==2){ atoIntgeger.getAndIncrement(); System.out.println("C"); System.out.println("\n"); } return true; } }); } public static void main(String[] args) throws Exception { log.info("------"); int i = 0; while(i < 10){ multPrint(); i++; log.info(String.format("第%d次打印>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",i)); log.info("\n"); } } }
AtomicInteger版本的实现有问题,有时可以实现ABC打印10次,有的情况下最后一次只能打印出A 或AB。
atoIntgeger.getAndIncrement(); 能保证线程安全箱,但是几个语句组合起来,无法保证线程安全的。
2 楼
nanjiwubing123
2015-12-29
参考你的用法,用如下方式实现。
@Slf4j public class TestUtil { private static AtomicInteger atoIntgeger = new AtomicInteger(0); public static void multPrint(){ ExecutorService excExecutorService = Executors.newFixedThreadPool(3); Future<Boolean> aFuture = excExecutorService.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { if(atoIntgeger.get() % 3 ==0){ atoIntgeger.getAndIncrement(); System.out.println("A"); } return true; } }); Future<Boolean> bFuture = excExecutorService.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { if(atoIntgeger.get() % 3 ==1){ atoIntgeger.getAndIncrement(); System.out.println("B"); } return true; } }); Future<Boolean> cFuture = excExecutorService.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { if(atoIntgeger.get() % 3 ==2){ atoIntgeger.getAndIncrement(); System.out.println("C"); System.out.println("\n"); } return true; } }); } public static void main(String[] args) throws Exception { log.info("------"); int i = 0; while(i < 10){ multPrint(); i++; log.info(String.format("第%d次打印>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",i)); log.info("\n"); } } }
1 楼
leecyz
2013-09-29
这个题 面试时碰到几次
发表评论
-
工厂类中移除if/else语句
2016-07-10 19:52 900面向对象语言的一个强大的特性是多态,它可以用来在代码中移除 ... -
Java编程练手100题
2014-12-11 17:13 6728本文给出100道Java编程练手的程序。 列表如下: 面 ... -
数组复制的三种方法
2014-11-30 12:57 2212本文将给出三种实现数组复制的方法 (以复制整数数组为例)。 ... -
数组复制的三种方法
2014-11-30 12:54 0本文将给出三种实现数组复制的方法 (以复制整数数组为例)。 ... -
四种复制文件的方法
2014-11-29 13:21 1739尽管Java提供了一个类ava.io.File用于文件的操 ... -
判断一个字符串中的字符是否都只出现一次
2014-11-25 12:58 2724本篇博文将给大家带来几个判断一个字符串中的字符是否都只出现一 ... -
使用正则表达式判断一个数是否为素数
2014-11-23 13:35 2166正则表达式能够用于判断一个数是否为素数,这个以前完全没有想过 ... -
几个可以用英文单词表达的正则表达式
2014-11-21 13:12 3748本文,我们将来看一下几个可以用英文单词表达的正则表达式。这些 ... -
(广度优先搜索)打印所有可能的括号组合
2014-11-20 11:58 1953问题:给定一个正整n,作为括号的对数,输出所有括号可能 ... -
随机产生由特殊字符,大小写字母以及数字组成的字符串,且每种字符都至少出现一次
2014-11-19 14:48 3976题目:随机产生字符串,字符串中的字符只能由特殊字符 (! ... -
找出1到n缺失的一个数
2014-11-18 12:57 3173题目:Problem description: You h ... -
EnumSet的几个例子
2014-11-14 16:24 8749EnumSet 是一个与枚举类型一起使用的专用 Set 实现 ... -
给定两个有序数组和一个指定的sum值,从两个数组中各找一个数使得这两个数的和与指定的sum值相差最小
2014-11-12 11:24 3327题目:给定两个有序数组和一个指定的sum值,从两个数组 ... -
Java面试编程题练手
2014-11-04 22:49 6700面试编程 写一个程序,去除有序数组中的重复数字 编 ... -
Collections用法整理
2014-10-22 20:55 9846Collections (java.util.Collect ... -
The Code Sample 代码实例 个人博客开通
2014-09-04 18:48 1417个人博客小站开通 http://thecodesample. ... -
Collections.emptyXXX方法
2014-06-08 13:37 2145从JDK 1.5开始, Collections集合工具类中预先 ... -
这代码怎么就打印出"hello world"了呢?
2014-06-08 00:37 7396for (long l = 4946144450195624L ... -
最短时间过桥
2014-04-21 22:03 4137本文用代码实现最短时间过桥,并且打印如下两个例子的最小过桥时间 ... -
将数组分割成差值最小的子集
2014-04-20 22:34 2899本文使用位掩码实现一个功能 ==》将数组分割成差值最小的子集 ...
相关推荐
46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...
### .NET面试题详解 #### 第2章 .NET框架基础 **2.1 .NET基础概念** - **2.1.1 什么是CTS、CLS和CLR?** - **CTS (Common Type System)**:公共类型系统是.NET框架的核心组件之一,它定义了一组规则来确保所有...
46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...
46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 32 47、sleep() 和 wait() 有什么区别? 33 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...
46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例说明...
72、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 18 73、线程的基本概念、线程的基本状态以及状态之间的关系 18 74、sleep() 和 wait() 有什么区别? 18 75、socket通信...
7. spring注入的几种方式(循环注入)。 Spring提供了多种注入方式,例如 setter注入、构造器注入和字段注入等。 8. spring如何实现事物管理的。 Spring提供了多种事务管理机制,例如使用@Transactional注解或使用...
46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 29 47、sleep() 和 wait() 有什么区别? 30 48、同步和异步有何异同,在什么情况下分别使用他们?举例...