求一个 Java 面试题的最佳实践

2021-01-25 12:24:37 +08:00
 Cbdy

三个线程,分别输出 a 、b 、c,各输出 100 次,要求按 abc 的顺序输出

期待输出为:abcabcabcabc...

4442 次点击
所在节点    Java
48 条回复
Vendettar
2021-01-25 14:20:52 +08:00
@ocean1477 咋不对呢 我这里输出是对的啊..
ocean1477
2021-01-25 14:24:08 +08:00
@Vendettar 这个是无法保证顺序的,1,2,3 三个线程可以同时进,争抢一个锁。
Vendettar
2021-01-25 14:28:08 +08:00
@ocean1477 公平锁不会争抢 你输出一下试试 顺序不会乱
ocean1477
2021-01-25 14:29:29 +08:00
@Vendettar 我这会试了下,会乱的,多试几次。
Thread-0:a
Thread-0:a
Thread-0:a
Thread-0:a
Thread-0:a
Thread-1:b
Thread-2:c
Thread-0:a
Thread-1:b
Thread-2:c
Thread-0:a
Thread-1:b
Thread-2:c
Thread-0:a
Thread-1:b
ocean1477
2021-01-25 14:32:03 +08:00
@Vendettar 看来老兄要重新看下公平锁了,公平锁≠顺序
Vendettar
2021-01-25 14:33:34 +08:00
@ocean1477 热 我试出来了 的确会乱
ocean1477
2021-01-25 14:38:19 +08:00
@Vendettar 哈哈,我无意指出,抱歉。
ssynhtn
2021-01-25 14:39:16 +08:00
用三个 Semaphore 就行了吧
Vendettar
2021-01-25 14:42:26 +08:00
@ocean1477 感谢指出
sczero
2021-01-25 14:43:56 +08:00
public static void main(String[] args) throws InterruptedException {
final AtomicReference<String> tag = new AtomicReference<>("a");
final int total = 100;
new Thread(() -> {
int count = 0;
while (count < total) {
if (tag.get().equals("a")) {
System.out.print("a");
tag.set("b");
count++;
}
}
}).start();
new Thread(() -> {
int count = 0;
while (count < total) {
if (tag.get().equals("b")) {
System.out.print("b");
tag.set("c");
count++;
}
}
}).start();
new Thread(() -> {
int count = 0;
while (count < total) {
if (tag.get().equals("c")) {
System.out.println("c");
tag.set("a");
count++;
}
}
}).start();
}
ssynhtn
2021-01-25 14:52:58 +08:00
public static void main(String[] args) {
Semaphore[] res = {
new Semaphore(1),
new Semaphore(0),
new Semaphore(0),
};

for (int i = 0; i < 3; i++) {
Semaphore current = res[i];
Semaphore next = res[(i + 1) % 3];
final char ch = (char) (i + 'a');
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 100; j++) {
try {
current.acquire();
System.out.print(ch);
next.release();
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}
}).start();
}

}
Cyron
2021-01-25 15:01:38 +08:00
简单公平锁实现
```
public class ReentrantLockDemo implements Runnable {

private static ReentrantLock lock = new ReentrantLock(true);

private String content;

public ReentrantLockDemo(String content) {
this.content = content;
}

@Override
public void run() {
while (true) {
try {
lock.lock();
System.out.println(content);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}

public static void main(String[] args) {
ReentrantLockDemo a = new ReentrantLockDemo("a");
ReentrantLockDemo b = new ReentrantLockDemo("b");
ReentrantLockDemo c = new ReentrantLockDemo("c");
Thread threadA = new Thread(a);
Thread threadB = new Thread(b);
Thread threadC = new Thread(c);
threadA.start();
threadB.start();
threadC.start();
}
}
```
zzh7982
2021-01-25 15:10:55 +08:00
不用加锁,join 就行了,刚测试了一把 没问题

https://gist.github.com/zzh7982/249883f379b50c5ae50eacd48736b5e2
kikione
2021-01-25 15:17:07 +08:00
我想到两个方案,第一个是加锁。 第二个是 join,b 等 a ,c 等 a 。
sczero
2021-01-25 15:20:33 +08:00
@zzh7982 新建了 300 个线程......至于吗....
zzh7982
2021-01-25 15:24:55 +08:00
@sczero 啊..这... 300 个线程都能控制顺序 这不显得水平高吗[dog]
kikione
2021-01-25 15:26:17 +08:00
for (int i=0;i<100;i++){
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
Thread3 thread3 = new Thread3();
thread1.start();
thread1.join();
thread2.start();
thread2.join();
thread3.start();
}
sampeng
2021-01-25 15:34:23 +08:00
都是有锁方案啊。。我提一个无锁和竞争的方案
三个队列。分别收 a,b,c 。
输出就是轮询这 3 个队列就好了。。一定都是有序的
johnson666
2021-01-25 16:05:58 +08:00
原子变量

public class Test {
public static void main(String[] args) {
AtomicInteger at = new AtomicInteger();
for (int i = 0; i < 3; i++) {
MyThread t = new MyThread(at, i);
t.start();
}
}
}

class MyThread extends Thread {
private AtomicInteger at;
private int index;

public MyThread(AtomicInteger at, int index) {
this.at = at;
this.index = index;
}

@Override
public void run() {
while(true) {
if(at.get() % 3 == index) {
System.out.print((char)('a' + index));
at.incrementAndGet();
}
}
}
}
Youen
2021-01-25 16:53:22 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/748114

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX