返回信息流最近碰到了这样一道面试题,要求:
自定义一个线程,创建三个实例,功能是打印1~100的数字。
其中,数字1+3*n(n>=0)必须是第一个线程实例打印的,2+3*n必须是第二个实例打印,3+3*n必须是第三个线程打印,打印结果严格递增,实例1,2,3依次轮流打印。
开始的想法线程类里边定义一个count初始化为1,打印count后另count++,然后将当前线程sleep一段时间。结果被面试官质疑这么做没办法保证实例1,实例2,实例3依次轮流这个顺序。
请问各位有什么思路么?
这是一条镜像帖。来源:北邮人论坛 / java / #41436同步于 2015/6/7
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
[面试题求助]多线程轮流打印数字
lkasdolka2
2015/6/7镜像同步31 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
public class Printer implements Runnable {
int i = 1;
public void run() {
try {
synchronized (this) {
while (i <= 100) {
String threadNo = Thread.currentThread().getName();
while (i % 3 != Integer.valueOf(threadNo) % 3) {
this.wait();
}
if (i <= 100)
System.out.println(threadNo + ": " + i++);
this.notifyAll();
}
}
} catch (InterruptedException e) {
System.out.println("InterruptedException occur");
}
}
}
public class Start {
public static void main(String[] args) {
Printer printer = new Printer();
Thread t1 = new Thread(printer,"1");
Thread t2 = new Thread(printer,"2");
Thread t3 = new Thread(printer,"3");
t1.start();
t2.start();
t3.start();
}
}
这样行吗?
来个简单粗暴无同步(真的没有吗?)的代码,帮忙看看是否正确。
package cn.byr.nuanyangyang.jishuqi;
class PrintingContext {
public volatile int current = 1;
}
class Printer implements Runnable {
private PrintingContext ctx;
private String name;
private int modulo;
public Printer(PrintingContext ctx, String name, int modulo) {
this.ctx = ctx;
this.name = name;
this.modulo = modulo;
}
@Override
public void run() {
while (true) {
int cur = ctx.current;
if (cur > 100) {
break;
}
if (cur % 3 == modulo) {
System.out.format("[%s] %d\n", name, cur);
int newNum = cur + 1;
ctx.current = newNum;
}
}
}
}
public class MangDengDaiJiShuQi {
public static void main(String[] args) throws Exception {
PrintingContext ctx = new PrintingContext();
Printer p1 = new Printer(ctx, "Printer 1", 1);
Printer p2 = new Printer(ctx, "Printer 2", 2);
Printer p3 = new Printer(ctx, "Printer 3", 0);
Thread t1 = new Thread(p1);
Thread t2 = new Thread(p2);
Thread t3 = new Thread(p3);
long timeStamp1 = System.currentTimeMillis();
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
long timeStamp2 = System.currentTimeMillis();
System.out.format("Total time: %dms", timeStamp2 - timeStamp1);
}
}
在网上看到一个三个线程轮流打印的,用信号量处理的,求问
b和c的信号量permit都是0,怎么实现轮流的呢?????
import java.util.concurrent.Semaphore;
public class SemaphoreThread extends Thread {
private Semaphore current;
private Semaphore next;
public SemaphoreThread(String name, Semaphore current, Semaphore next) {
super(name);
this.current = current;
this.next = next;
}
public void run() {
for (int i = 0; i < 10; i++) {
try {
current.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(this.getName());
next.release();
}
}
public static void main(String[] args) {
Semaphore a = new Semaphore(1);
Semaphore b = new Semaphore(0);
Semaphore c = new Semaphore(0);
new SemaphoreThread("A", a, b).start();
new SemaphoreThread("B", b, c).start();
new SemaphoreThread("C", c, a).start();
}
}
【 在 nuanyangyang 的大作中提到: 】
: 来个简单粗暴无同步(真的没有吗?)的代码,帮忙看看是否正确。
: [code=java]
: package cn.byr.nuanyangyang.jishuqi;
: ...................
【 在 homeless271 的大作中提到: 】
: 在网上看到一个三个线程轮流打印的,用信号量处理的,求问
:
: b和c的信号量permit都是0,怎么实现轮流的呢?????
: ...................
a执行next.release的时候,b的信号量就是1了。b执行next.release的时候c的就是1了。
另外,怎么都这么喜欢try {
} catch (InterruptedException e) {
e.printStackTrace();
}
赞一个
【 在 Monologue 的大作中提到: 】
: public class Printer implements Runnable {
: int i = 1;
: public void run() {
: ...................
暖神V5
【 在 nuanyangyang 的大作中提到: 】
: 来个简单粗暴无同步(真的没有吗?)的代码,帮忙看看是否正确。
: [code=java]
: package cn.byr.nuanyangyang.jishuqi;
: ...................
暖神好~~
话说我把这个volatile去掉之后程序有时候运行会直接卡死(什么也不输出,但是还是跑),但是从这个程序上面看
共享的变量值总有个(i)%3==mod符合的,为什么会卡死呢?
可见性和有序性吗?= = 但是感觉这个问题最多导致重复或者乱序,求教~~[ema1]
【 在 nuanyangyang 的大作中提到: 】
: 来个简单粗暴无同步(真的没有吗?)的代码,帮忙看看是否正确。
: [code=java]
: package cn.byr.nuanyangyang.jishuqi;
: ...................
【 在 Lamperouge 的大作中提到: 】
: 暖神好~~
: 话说我把这个volatile去掉之后程序有时候运行会直接卡死(什么也不输出,但是还是跑),但是从这个程序上面看
: 共享的变量值总有个(i)%3==mod符合的,为什么会卡死呢?
: ...................
比如T1、T2、T3分别看到的ctx.current都总是某个常数,从来看不到另外两个线程写进去的结果,比如T1第一次看到2以后就永远只看到2,T2永远只看到0,T3永远只看到1。即使这样,也并没有违反规则:每次读看到的总是以前某次写进去的值。即:
T1: cur = ctx.current (看到1)
T1: ctx.current = 2
T2: cur = ctx.current (看到2)
T2: ctx.current = 0
T3: cur = ctx.current (看到0)
T3: ctx.current = 1
T1: cur = ctx.current (看到2)(这是合法的。T1可以看到自己写的2,没有必要看到T2写的0,也没有必要看到T3写的1)
T2: cur = ctx.current (看到0)(这是合法的。T2可以看到自己写的0,没有必要看到T1写的2,也没有必要看到T3写的1)
T3: cur = ctx.current (看到1)(这是合法的。T3可以看到自己写的1,没有必要看到T1写的2,也没有必要看到T2写的0)
T1: cur = ctx.current (看到2)
T2: cur = ctx.current (看到0)
T3: cur = ctx.current (看到1)
T1: cur = ctx.current (看到2)
T3: cur = ctx.current (看到1)
T2: cur = ctx.current (看到0)
T2: cur = ctx.current (看到0)
T1: cur = ctx.current (看到2)
T3: cur = ctx.current (看到1)
T1: cur = ctx.current (看到2)
T2: cur = ctx.current (看到0)
T3: cur = ctx.current (看到1)
。。。这样如此循环,程序再也没有取得进展,但这也是合法的执行结果。
但是当ctx.current是volatile的以后,就不一样了:所有线程对ctx.current的读写必须有一个全局的全序关系,所以三个线程每次读总是读到最后一次写的,总会有一个前进。这时候如果3个线程都不前进,它们就必定有一个线程看到的不是最后一次写的。