class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
※実行中のスレッドいつ停止?
・当线程A试图去获得一个JUC锁,但这个锁却已经被另外一个线程获得,那么线程A不得不“停止”,直到这个锁被释放或者超时。
・当线程A调用了java.util.concurrent.locks.Condition的任意一个“等待”的API,线程A会停止执行,直到另外一个线程通知它或者超时。
※
多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问。要想实现线程的同步,则这些线程必须去竞争一个唯一的共享的对象锁。
=>共享的资源是必须的,要不然大家没有关系了吗,也就不会相互同步了...
.
※
虽然run()函数实现了多个线程的并行处理,但我们不能直接调用run()函数,而是通过调用start()函数来调用run()函数。在调用
start()的时候,start()函数会首先进行与多线程相关的初始化(这也是为什么不能直接调用run()函数的原因),然后再调用run()函数
※
我们只用new产生Thread对象,并没有用reference来记录所产生的Thread对象。根据垃圾回收机制,当一个对象没有被
reference引用时,它将被回收。但是垃圾回收机制对Thread对象“不成立”。因为每一个Thread都会进行注册动作,所以即使我们在产生
Thread对象时没有指定一个reference指向这个对象,实际上也会在某个地方有个指向该对象的reference,所以垃圾回收器无法回收它
们。
※
suspend()函数只是让当前线程进入停滞状态,但并不释放当前线程所获得的“锁标志”。当前对象的“锁标志”仍被线程占有。
※JAVA对象里内置了隐性的锁, 用synchronized时就使用了相关对象的锁...
※MAIN也是一个线程,通过currentThead()可以获取它,对它进行控制
★SynchronousQueue のおかげで、キューに挿入された項目を利用しようと待機しているスレッドがない限りキューに挿入することはできません.
==>要するに、怖い消費者が生産ラインで待っている。
物を生産しInsertの後、すぐ別のスレッドがそれを取り出して消費する。
容量がないQueue
★Semaphore=>スレッドの定員、その数超えたスレッドがparkingにする(WAITING) Semaphore.acquire(); Semaphore.release()
java.lang.Thread.State: WAITING (parking)=>has no right to run.
★CountDownLatch クラスは特定の条件が満たされるまですべてのスレッドを保留し、その条件が満たされると、すべてのスレッドを同時に解放
==>「よい準備、3、2、1、スタート。。」の感じだね。。CountDownLatch名前の通り。
★スレッドの新作成と再利用
=>
一部の JVM では Thread の作成は非常に面倒な作業であり、既存の Thread を再利用した方が新しい Thread を作成するよりもはるかに望ましい。
しかし他の JVM では、それがまったく逆。つまり Thread は非常に軽量であり、必要な時に new によって単純に新しい Thread を作成した方がはるかに望ましい。
==>なにこれ、困るね。。。
===>JSR-166 Expert Group (「参考文献」を参照) は、この状況をある程度想定した。Java 開発者に Thread を直接作成させる代わりに、彼らは新しいスレッドを作成するための抽象インターフェース Executor を導入し、スレッドを作成することができた
====>こいつらたちが、問題を回避したね。。。みえなくなった。。。