这是 java 编程思想的一个小例子,大概意思,五个 Runnable 对象会对自己加锁(但对自己加锁,因为没有别人和它本身冲突,所以没有意义),还有个 Count 对象,它也有同步方法,五个线程都会调到它,自然,只有它的同步方法才是有意义的。
import java.util.concurrent.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import static net.mindview.util.Print.*;
class Count {
private int count = 0;
private Random rand = new Random(47);
// Remove the synchronized keyword to see counting fail:
public synchronized int increment() {
int temp = count;
System.out.println(Thread.currentThread().getName()+" befor yield");
if(rand.nextBoolean()) // Yield half the time
Thread.yield();
System.out.println(Thread.currentThread().getName()+" after yield");
return (count = ++temp);
}
public synchronized int value() { return count; }
}
class Entrance implements Runnable {
private static Count count = new Count();
private static List<Entrance> entrances =
new ArrayList<Entrance>();
private int number = 0;
// Doesn't need synchronization to read:
private final int id;
private static volatile boolean canceled = false;
// Atomic operation on a volatile field:
public static void cancel() { canceled = true; }
public Entrance(int id) {
this.id = id;
// Keep this task in a list. Also prevents
// garbage collection of dead tasks:
entrances.add(this);
}
public void run() {
while(!canceled) {
synchronized(this) {
++number;
}
print(this + " Total: " + count.increment());
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch(InterruptedException e) {
print("sleep interrupted");
}
}
print("Stopping " + this);
}
public synchronized int getValue() { return number; }
public String toString() {
return "Entrance " + Thread.currentThread().getName() + ": " + getValue();
}
public static int getTotalCount() {
return count.value();
}
public static int sumEntrances() {
int sum = 0;
for(Entrance entrance : entrances)
sum += entrance.getValue();
return sum;
}
}
public class OrnamentalGarden {
public static void main(String[] args) throws Exception {
AtomicInteger a = new AtomicInteger();
ExecutorService exec = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),new ThreadFactory(){ public Thread newThread(Runnable r) {
return new Thread(r, "pool_" + a.getAndIncrement());
}});
for(int i = 0; i < 5; i++)
exec.execute(new Entrance(i));
// Run for a while, then stop and collect the data:
TimeUnit.SECONDS.sleep(3);
Entrance.cancel();
exec.shutdown();
if(!exec.awaitTermination(250, TimeUnit.MILLISECONDS))
print("Some tasks were not terminated!");
print("Total: " + Entrance.getTotalCount());
print("Sum of Entrances: " + Entrance.sumEntrances());
}
}
可能好多人看到这里直接略过了,但我看完这个例子确实似懂非懂的。https://paste.ubuntu.com/p/B7GQMcMhv7/ ,这是原版代码,为了看到简单的线程名,稍微改了下。执行完后,打印结果是:
pool_0 befor yield
pool_0 after yield
pool_2 befor yield
pool_2 after yield
pool_4 befor yield
pool_4 after yield
pool_3 befor yield
pool_3 after yield
pool_1 befor yield
pool_1 after yield
Entrance pool_0: 1 Total: 1
Entrance pool_3: 1 Total: 4 为啥这里直接是 4 了?
Entrance pool_1: 1 Total: 5
Entrance pool_2: 1 Total: 2
Entrance pool_4: 1 Total: 3
pool_0 befor yield
pool_0 after yield
如上,为啥那里直接是 4 了?那个 4 是 count 对象的同步方法,按理说应该接下来打印 2 啊。所以这个程序是想说明,1 过了直接打印 4,是因为线程调度吗?作者想说明什么啊
PS:有时候感觉 Java 编程思想的例子好恶心。。。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.