使用CAS变量和CountDownLatch保证线程间的同步
//使用CAS变量和CountDownLatch保证线程间的同步-匀速的发送短信
public class ThreadSync {
private AtomicLong total = new AtomicLong(0);
private volatile boolean isstop = false;
private volatile AtomicBoolean hasNotified = new AtomicBoolean(false);
private CountDownLatch2 waitPoint = new CountDownLatch2(1);
public static void main(String[] args) {
final ThreadSync o = new ThreadSync();
ThreadA t1 = o.new ThreadA("t1");
t1.start();
//每隔2秒唤醒t1线程
new Thread(){
public void run(){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(!o.getHasNotified().get()){
o.wakeup();
}
}
}.start();
}
class ThreadA extends Thread{
public ThreadA(String name){
super(name);
}
public void run() {
while(!isstop){
waitForRunning(500);
System.out.println(this.getName()+" " + total.getAndIncrement() + " "+timeMillisToHumanString(new Date().getTime()));
}
}
}
public void wakeup() {
if (hasNotified.compareAndSet(false, true)) {
waitPoint.countDown(); // notify
}
}
protected void waitForRunning(long interval) {
if (hasNotified.compareAndSet(true, false)) {
System.out.println("***");
return;
}
waitPoint.reset();
try {
waitPoint.await(interval, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
hasNotified.set(false);
}
}
public AtomicBoolean getHasNotified() {
return hasNotified;
}
public static String timeMillisToHumanString(final long t) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(t);
return String.format("%04d%02d%02d%02d%02d%02d%03d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1,
cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND),
cal.get(Calendar.MILLISECOND));
}
}
//增加了reset方法
public class CountDownLatch2 {
private final Sync sync;
public CountDownLatch2(int count) {
if (count < 0)
throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public void countDown() {
sync.releaseShared(1);
}
public long getCount() {
return sync.getCount();
}
public void reset() {
sync.reset();
}
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
private final int startCount;
Sync(int count) {
this.startCount = count;
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
for (; ; ) {
int c = getState();
if (c == 0)
return false;
int nextc = c - 1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
protected void reset() {
setState(startCount);
}
}
}
分享到:
相关推荐
`CountDownLatch` 是一个计数器,可以用于协调多个线程间的活动,等待所有线程完成各自的任务后,主线程或其他线程才能继续执行。 首先,让我们深入理解 `CountDownLatch` 的工作原理。`CountDownLatch` 在构造时会...
这个问题通常用于演示和理解线程间的协作机制,如互斥锁、条件变量等。在此,我们将深入探讨这个问题的背景、解决方案以及Java中实现这些解决方案的方法。 生产者消费者问题是这样的:一个系统有两个主要的角色,...
3. **wait()、notify() 和 notifyAll()** 方法:这些方法是Object类中的,用于线程间通信。一个线程调用`wait()`会释放同步锁并进入等待状态,直到其他线程调用`notify()`或`notifyAll()`唤醒它。 4. **java.util....
在Java并发编程中,`CountDownLatch`是一个同步辅助类,它允许多个线程等待其他线程完成操作。在批量插入数据的场景下,可以创建一个CountDownLatch对象,初始化为线程的数量,每个线程处理完自己的数据后调用`...
总之,CountDownLatch是Java多线程编程中的一个重要工具,通过它可以实现线程间的同步与协作,有效地解决了多线程环境下任务的同步问题。理解其工作原理和应用场景,能帮助开发者更好地设计和优化并发程序。
- **volatile**关键字:保证变量在多个线程间可见性,但不保证原子性。 - **Atomic包**:提供一系列原子操作类,如`AtomicInteger`、`AtomicLong`,保证操作的原子性和可见性。 3. **基于HTTP的断点续传**: - *...
Java提供了多种机制,如wait()、notify()和notifyAll()方法,以及Semaphore、BlockingQueue等并发工具类,用于线程间的通信和协作。 7. **线程优先级**: 操作系统为每个线程分配了一个优先级,但这并不保证高...
`await()`方法利用了`java.util.concurrent.locks.Condition`来阻塞和唤醒线程,确保线程间的同步。 7. **注意事项** - CountDownLatch不支持重置,一旦计数器归零,就无法再次使用。如果需要重复使用,考虑使用...
- **wait()与notify()**:用于线程间的通信,等待和唤醒其他线程。 - **Lock接口**:提供更灵活的锁机制,如ReentrantLock。 3. **线程池** - **Executor框架**:Java提供的线程池服务,可减少线程创建和销毁的...
- **JMM(Java Memory Model)**:理解JMM对于理解线程间的数据可见性和有序性至关重要,它规定了线程如何访问和修改共享变量。 10. **线程安全问题** - **竞态条件**:当多个线程并发访问和更新共享变量,可能...
在多线程编程中,线程通信是一个至关重要的概念,特别是在并发执行任务时,确保不同线程间的协作和数据同步。本教程将聚焦于利用事件对象进行线程间的通信,这是实现多线程同步的一种常见方法。 事件对象,通常称为...
- `CyclicBarrier`允许一组线程等待所有线程到达屏障点后一起继续执行,适用于线程间的协同工作。 - `CountDownLatch`通常用于一次性事件,当计数器归零时,所有等待的线程才能继续执行。 - `Exchanger`则允许两...
此外,`wait()`和`notify()`(或`notifyAll()`)方法用于线程间的通信,让线程在等待资源时释放CPU,并在资源可用时唤醒。Java还提供了`ReentrantLock`可重入锁,它具有更高的灵活性,可以实现更复杂的同步策略。`...
这种问题通常通过线程间通信和同步机制来解决,如`synchronized`关键字、`wait()`、`notify()`或`notifyAll()`方法,以及`Semaphore`、`CyclicBarrier`等高级并发工具。下面我们将深入探讨这些概念和方法。 首先,`...
使用 CountDownLatch 可以使得多个线程之间的同步操作变得更加容易和高效。 CountDownLatch 是一种非常有用的同步工具,能够实现多个线程之间的同步操作,避免了线程之间的互相干扰。它可以获取返回值,并且易于...
Java 使用 CountDownLatch 等待多线程全部执行完成 CountDownLatch 是 Java 中的...CountDownLatch 是 Java 中一个非常强大且灵活的同步工具类,使用它可以轻松地实现多线程的同步操作,提高程序的执行效率和可靠性。
5. **线程间通信**:除了锁机制,JVM还提供了一系列的线程间通信工具,如`ThreadLocal`、`Wait/Notify`、`CountDownLatch`、`Semaphore`、`CyclicBarrier`等,用于解决线程间的同步问题,使多线程程序更加灵活和可控...
- `wait()`, `notify()`和`notifyAll()`方法用于线程间通信,需在同步环境中使用。 5. **线程通信问题** - 生产者-消费者问题:一个线程生产数据,另一个线程消费数据,需要避免生产者过度生产或消费者提前消费。...
在Java编程中,线程间的通信是多线程编程中的一个重要概念,特别是在处理并发和协作任务时。生产者消费者模型是一种经典的线程同步问题,它模拟了实际生活中的生产过程和消费过程,使得生产者线程可以将数据生产出来...
Java并发包`java.util.concurrent`提供了如`Semaphore`(信号量)、`CountDownLatch`(计数器)、`CyclicBarrier`(回环栅栏)等工具,它们是设计来协助多线程间的协作和同步的。 理解并熟练运用这些知识点,可以...