java启动3个线程轮流打印数字
转自:http://blog.csdn.net/u014011112/article/details/50988769
http://blog.csdn.net/perrywork/article/details/16819153
- //一个关于线程的经典面试题,要求用三个线程,按顺序打印1,2,3,4,5.... 71,72,73,74, 75.
- //线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后是线程3打印11,12,13,14,15.
- //接着再由线程1打印16,17,18,19,20....以此类推, 直到线程3打印到75。
- public class Printer implements Runnable {
- int id;
- static int num = 1;
- public Printer(int id) {
- this.id = id;
- }
- @Override
- public void run() {
- synchronized (Printer.class) {
- while (num <= 75) {
- if (num / 5 % 3 == id) {
- System.out.print("id" + id + ":");
- for (int i = 0; i < 5; i++)
- System.out.print(num++ + ",");
- System.out.println();
- Printer.class.notifyAll();
- } else {
- try {
- Printer.class.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
- public static void main(String[] args) {
- new Thread(new Printer(0)).start();
- new Thread(new Printer(1)).start();
- new Thread(new Printer(2)).start();
- }
- }
打印结果:
- id0:1,2,3,4,5,
- id1:6,7,8,9,10,
- id2:11,12,13,14,15,
- id0:16,17,18,19,20,
- id1:21,22,23,24,25,
- id2:26,27,28,29,30,
- id0:31,32,33,34,35,
- id1:36,37,38,39,40,
- id2:41,42,43,44,45,
- id0:46,47,48,49,50,
- id1:51,52,53,54,55,
- id2:56,57,58,59,60,
- id0:61,62,63,64,65,
- id1:66,67,68,69,70,
- id2:71,72,73,74,75,
/////////////////////////////////////////////////////////////////////////////
原帖见:http://www.iteye.com/topic/1117703
问题描述:
一个关于线程的经典面试题,要求用三个线程,按顺序打印1,2,3,4,5.... 71,72,73,74, 75.
线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后是线程3打印11,12,13,14,15. 接着再由线程1打印16,17,18,19,20....以此类推, 直到线程3打印到75。
直接上代码:
- package concurrent.test;
- /**
- * 要求创建三个线程,输出1-75,
- * 最开始第一个线程输出1-5,第二个输出6-10,第三个输出11-15
- * 接着再第一个线程输出16-20...就这样循环下去,直到打印出75个数
- * @author qiaoxueshi
- *
- */
- public class Print1to75 {
- static class Printer implements Runnable{
- static int num = 1; //开始数字
- static final int END = 75;
- int id;
- public Printer(int id) {
- this.id = id;
- }
- @Override
- public void run(){
- synchronized (Printer.class) {
- while(num <= END){
- if(num / 5 % 3 == id){ //如果是属于自己的数,依次打印出来五个
- System.out.print(id + ":");
- for(int i = 0; i < 5; i++){
- System.out.print(num++ + ", ");
- }
- System.out.println();
- Printer.class.notifyAll();//放弃CPU使用权,唤醒等待在Print.class队列上的的打印线程
- }else{
- try {
- Printer.class.wait();//如果不属于自己的数,把当前线程挂在Printer.class这个对象的等待队列上(也是放弃CPU使用权),等待唤醒
- } catch (InterruptedException e) {
- System.out.println("id" + "被打断了");
- }
- }
- }
- }
- }
- }
- public static void main(String[] args) {
- //下面可以不按0,1,2的顺序来,而且在两两中间随便sleep(),都会正确打印出来
- new Thread( new Printer(0)).start();
- new Thread( new Printer(1)).start();
- new Thread( new Printer(2)).start();
- }
- }
注释中说的也很明白,有问题欢迎大家讨论。
结果(运行了N次,结果都是一致的,请大家检验):
- 0:1, 2, 3, 4, 5,
- 1:6, 7, 8, 9, 10,
- 2:11, 12, 13, 14, 15,
- 0:16, 17, 18, 19, 20,
- 1:21, 22, 23, 24, 25,
- 2:26, 27, 28, 29, 30,
- 0:31, 32, 33, 34, 35,
- 1:36, 37, 38, 39, 40,
- 2:41, 42, 43, 44, 45,
- 0:46, 47, 48, 49, 50,
- 1:51, 52, 53, 54, 55,
- 2:56, 57, 58, 59, 60,
- 0:61, 62, 63, 64, 65,
- 1:66, 67, 68, 69, 70,
- 2:71, 72, 73, 74, 75,
注意第23行的synchronized (Printer.class) ,为什么是Printer.class,而不是this呢?
是因为Print.class也是一个对象,在当前JVM中是唯一的,它相当于一个“公证人”,三个线程竞争资源的时候都是从唯一的这个“公证人”手里拿到许可,才能进入synchronized体。
而如果是synchronized (this)的话,this也相当于一个“公证人”,那么三个线程各自有一个“公证人”,相当于各干各的,三个中间没有竞争关系,构不成同步。
可见只要是这三个的“公证人”是同一个家伙,就能保持同步,稍微修改一下代码,我们给三个线程传进去同一个“公证人”(其实就是一个普通的不能再普通的对象):
- package concurrent.test;
- /**
- * 要求创建三个线程,输出1-75,
- * 最开始第一个线程输出1-5,第二个输出6-10,第三个输出11-15
- * 接着再第一个线程输出16-20...就这样循环下去,直到打印出75个数
- * @author qiaoxueshi
- *
- */
- public class Print1to75 {
- static class Printer implements Runnable{
- static int num = 1; //开始数字
- static final int END = 75;
- int id;
- Object o; //这就是三个线程的“公证人”,有点寒酸吧
- public Printer(int id, Object o) {
- this.id = id;
- this.o = o;
- }
- @Override
- public void run(){
- synchronized (o) {
- while(num <= END){
- if(num / 5 % 3 == id){ //如果是属于自己的数,依次打印出来五个
- System.out.print(id + ":");
- for(int i = 0; i < 5; i++){
- System.out.print(num++ + ", ");
- }
- System.out.println();
- o.notifyAll();//放弃CPU使用权,唤醒在o对象的等待队列上的线程
- }else{
- try {
- o.wait(); //如果不属于自己的数,把当前线程挂在o这个对象的等待队列上(也放弃了CPU使用权),等待唤醒
- } catch (InterruptedException e) {
- System.out.println("id" + "被打断了");
- }
- }
- }
- }
- }
- }
- public static void main(String[] args) {
- //下面可以不按0,1,2的顺序来,而且在两两中间随便sleep(),都会正确打印出来
- Object o = new Object();
- new Thread( new Printer(0, o)).start();
- new Thread( new Printer(1, o)).start();
- new Thread( new Printer(2, o)).start();
- }
- }
在第16行,添加了三个线程的”公证人“ Object o;
第25,34,37行都由原来的Printer.class改为了o;
在第50行,创建了一个Object对象,传给了三个线程。
运行结果和上面的是一模一样地!
- new Thread( new Printer(0, o)).start();
- new Thread( new Printer(1, o)).start();
- new Thread( new Printer(2, o)).start();
如果觉得这段不太优雅,可以使用ExecuorService来实现,道理是一样的。
java启动3个线程轮流打印数字的更多相关文章
- Java n个线程轮流打印数字的问题
一. 实现两个线程.轮流打印出数字.例如以下: bThread --> 10 aThread --> 9 bThread --> 8 aThread --> 7 bThread ...
- 使用Java实现三个线程交替打印0-74
使用Java实现三个线程交替打印0-74 题目分析 三个线程交替打印,即3个线程是按顺序执行的.一个线程执行完之后,唤醒下一个线程,然后阻塞,等待被该线程的上一个线程唤醒.执行的顺序是一个环装的队列 ...
- Java多个线程顺序打印数字
要求 启动N个线程, 这N个线程要不间断按顺序打印数字1-N. 将问题简化为3个线程无限循环打印1到3 方法一: 使用synchronized 三个线程无序竞争同步锁, 如果遇上的是自己的数字, 就打 ...
- Java之进程与线程练习
1.设计一个线程类:创建3个子线程,每个线程分别打印数字,分别睡眠100,200,300ms ->每个执行都是20次 代码: package Homework; //1.设计一个线程类:创建3个 ...
- 迅雷笔试题 (JAVA多线程)启动三个线程,分别打印A B C,现在写一个程序 循环打印ABCABCABC
题目:http://wenku.baidu.com/view/d66187aad1f34693daef3e8a.html 启动三个线程,分别打印A B C,现在写一个程序 循环打印ABCABCABC. ...
- 使用Java线程并发库实现两个线程交替打印的线程题
背景:是这样的今天在地铁上浏览了以下网页,看到网上一朋友问了一个多线程的问题.晚上闲着没事就决定把它实现出来. 题目: 1.开启两个线程,一个线程打印A-Z,两一个线程打印1-52的数据. 2.实现交 ...
- 使用Java 多线程编程 让三个线程轮流输出ABC,循环10次后结束
简要分析: 要求三个线程轮流输出,这里我们要使用一个对象锁,让关键部分的代码放入同步块当中.同时要有一个变量记录打印的次数到达10次循环后不再打印,另外一个就是要给每个线程一个标志号,我们根据标识号来 ...
- Java 启动线程的方式
面试题:JAVA启动线程的方式有哪些? 1.继承Thread [java] view plaincopy public class java_thread extends Thread{ public ...
- Java线程同步打印ABC
需求: 三个线程,依次打印ABCABCABC.... 方案一: 使用阻塞队列,线程1从队列1获取内容打印,线程2从队列2获取内容打印,线程3从队列3中获取内容打印.线程1把B放到队列3中,线程2把C放 ...
随机推荐
- win7下hadoop编程eclipse的配置
本人hadoop初学,折腾第一个hadoop1.1.2花了好几天,让各位见笑了, WARN NativeCodeLoader:52 - Unable to load native-hadoop lib ...
- 微信小程序——获取绑定事件元素的ID
小程序list数据带值跳转,一般直接通过设置item的id来标识或者通过设置键值data-xxxx的方式标识.如下图所示: 解析出来的结果如下图: 我们看到它在元素上绑定了一个checkSchoolL ...
- 从 QA 到 EP
两三年以前,和友人谈到 QA(软件质量保证) 这个行业,还有 QA 这个团队的未来,就有了一丝忧虑.而现在,终于有机会实践一下自己之前的想法,在这里分享给大家. 从我有限的从业经验到现在,经历了很多次 ...
- fprintf宏
最近在调试程序,使用printf函数和调试信息都不能在终端输出,所以使用比较笨的方法.将调试信息写到文件中,再查看文件.由于要多次使用fprintf函数,所以将其写成宏. 参考链接: http://w ...
- C#有关的vshost、exe、config格式说明
vshost.exe.config是程序运行时的配置文本 exe.config是程序运行后会复制到vshost.exe.config app.config是在vshost.exe.config和exe ...
- (转)ffplay的音视频同步分析之视频同步到音频
以前工作中参与了一些音视频程序的开发,不过使用的都是芯片公司的SDK,没有研究到更深入一层,比如说音视频同步是怎么回事.只好自己抽点时间出来分析开源代码了,做音视频编解码的人都知道ffmp ...
- Javascript实用代码片段(译)
原文:http://www.bestdesigntuts.com/10-time-saving-javascript-code-snippets-for-web-developers 1. 同高或同宽 ...
- nodejs基础 -- 模块系统
为了让nodejs的文件可以相互调用,nodejs提供了一个简单的模块系统. 模块:是nodejs应用程序的基本组成部分,文件和模块一一对应.即,一个nodejs文件就是一个模块,这个文件可能是jav ...
- Android SDK的安装教程
Android4.1虽说已经发布了好些天,但由于的我手机比较坑,系统依旧保持在2.3.4.0的都是可望不可即的了,就别说4.1.由于资金的问题,没法换手机,只能另想方法,通过在笔记本上装andro ...
- 《R语言入门》语言及环境简单介绍
简单介绍 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/diss ...