1、Object#wait(), Object#notify()让两个线程依次执行

/**
* 类AlternatePrintDemo.java的实现描述:交替打印
*/
class NumberPrint implements Runnable {
private int number;
public byte res[];
public static int count = 5; public NumberPrint(int number, byte a[]) {
this.number = number;
res = a;
} public void run() {
synchronized (res) {
while (count-- > 0) {
try {
res.notify();//唤醒等待res资源的线程,把锁交给线程(该同步锁执行完毕自动释放锁)
System.out.println(" " + number);
res.wait();//释放CPU控制权,释放res的锁,本线程阻塞,等待被唤醒。
System.out.println("------线程" + Thread.currentThread().getName() + "获得锁,wait()后的代码继续运行:" + number);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
} public class AlternatePrintDemo {
public static void main(String args[]) {
final byte a[] = { 0 };//以该对象为共享资源
new Thread(new NumberPrint(1, a), "1").start();
new Thread(new NumberPrint(2, a), "2").start();
}
}

2、Condition#signal(), Condition#wait()让两个线程依次执行

/**
*
* 类ConditionDemo.java的实现描述:Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,
* 为每个对象提供多个等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
*/
public class ConditionDemo {
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {
@Override
public void run() {
threadExecute(business, "sub");
}
}).start();
threadExecute(business, "main");
} public static void threadExecute(Business business, String threadType) {
for (int i = 0; i < 10; i++) {
try {
if ("main".equals(threadType)) {
business.main(i);
} else {
business.sub(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} class Business {
private boolean bool = true;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition(); public /* synchronized */ void main(int loop) throws InterruptedException {
lock.lock();
try {
while (bool) {
condition.await();//this.wait();
}
System.out.println("main thread seq loop of " + loop); bool = true;
condition.signal();//this.notify();
} finally {
lock.unlock();
}
} public /* synchronized */ void sub(int loop) throws InterruptedException {
lock.lock();
try {
while (!bool) {
condition.await();//this.wait();
} System.out.println("sub thread seq loop of " + loop); bool = false;
condition.signal();//this.notify();
} finally {
lock.unlock();
}
}
}

Lock.Condition同理

import java.util.concurrent.locks.*;

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;//如果写索引写到队列的最后一个位置了,那么置为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;//如果读索引读到队列的最后一个位置了,那么置为0
--count;//个数--
notFull.signal();//唤醒写线程
return x;
} finally {
lock.unlock();
}
}
}

3、两个线程使用Object#wait(), Object#notify()实现生产消费者模式。

/**
*
* 类ProducerConsumerDemo.java的实现描述:生产消费者模式
*/
public class ProducerConsumerDemo { public static void main(String args[]) { final Queue<Integer> sharedQ = new LinkedList<>(); Thread producer = new Producer(sharedQ);
Thread consumer = new Consumer(sharedQ); producer.start();
consumer.start(); }
} class Producer extends Thread {
private static final int MAX_COUNT = 10;
private Queue<Integer> sharedQ; public Producer(Queue<Integer> sharedQ) {
super("Producer");
this.sharedQ = sharedQ;
} @Override
public void run() {
for (int i = 0; i < MAX_COUNT; i++) {
synchronized (sharedQ) {
//waiting condition - wait until Queue is not empty
while (sharedQ.size() >= 1) {
try {
System.out.println("Queue is full, waiting");
sharedQ.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("producing : " + i);
sharedQ.add(i);
sharedQ.notify();
}
}
}
} class Consumer extends Thread {
private Queue<Integer> sharedQ; public Consumer(Queue<Integer> sharedQ) {
super("Consumer");
this.sharedQ = sharedQ;
} @Override
public void run() {
while (true) {
synchronized (sharedQ) {
//waiting condition - wait until Queue is not empty
while (sharedQ.size() == 0) {
try {
System.out.println("Queue is empty, waiting");
sharedQ.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
int number = (int) sharedQ.poll();
System.out.println("consuming : " + number);
sharedQ.notify(); //termination condition
if (number == 3) {
break;
}
}
}
}
}

4、CountDownLatch实现类似计数器的功能。

/**
*
* 类CountDownLatchDemo.java的实现描述:CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能.
* 调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
*/
public class CountDownLatchDemo {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(2); new Thread() {
public void run() {
try {
System.out.println("子线程" + Thread.currentThread().getName() + "正在执行");
Thread.sleep(3000);
System.out.println("子线程" + Thread.currentThread().getName() + "执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start(); new Thread() {
public void run() {
try {
System.out.println("子线程" + Thread.currentThread().getName() + "正在执行");
Thread.sleep(3000);
System.out.println("子线程" + Thread.currentThread().getName() + "执行完毕");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start(); try {
System.out.println("等待2个子线程执行完毕...");
latch.await();
System.out.println("2个子线程已经执行完毕");
System.out.println("继续执行主线程");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

5、 CyclicBarrier(回环栅栏)可以实现让一组线程等待至某个状态之后再全部同时执行。

/**
* 类CyclicBarrierDemo.java的实现描述:字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。
* 叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,
* 线程就处于barrier了。
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {
int N = 4;
//所有线程写入操作完之后,进行额外的其他操作可以为CyclicBarrier提供Runnable参数
CyclicBarrier barrier = new CyclicBarrier(N, new Runnable() {
@Override
public void run() {
System.out.println("当前线程" + Thread.currentThread().getName());
}
});
for (int i = 0; i < N; i++) {
if (i < N - 1) {
new Writer(barrier).start();
} else {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Writer(barrier).start();
}
} System.out.println("CyclicBarrier重用"); for (int i = 0; i < N; i++) {
new Writer(barrier).start();
}
} static class Writer extends Thread {
private CyclicBarrier cyclicBarrier; public Writer(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
} @Override
public void run() {
System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据...");
try {
Thread.sleep(5000); //以睡眠来模拟写入数据操作
System.out.println("线程" + Thread.currentThread().getName() + "写入数据完毕,等待其他线程写入完毕");
try {
cyclicBarrier.await(2000, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("所有线程写入完毕,继续处理其他任务...");
}
}
}

6、Semaphore用来控制同时访问某一资源的操作数量,或控制同时执行某个指定操作的数量。

/**
* 类SemaphoreDemo.java的实现描述:Semaphore用来控制同时访问某一资源的操作数量,或控制同时执行某个指定操作的数量。
* 主要通过控制一组虚拟的“许可”,当需要执行操作时首先申请获取许可,如果还有剩余的许可 并且获取成功,就执行操作;如果剩余许可为0,就阻塞当前线程;
* 操作执行完成后释放许可,排队的阻塞线程可以被唤醒重新获取许可继续执行。这里提到排队,其实就是利用AQS的队列进行排队。
*/
public class SemaphoreDemo {
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool(); // 只能5个线程同时访问
final Semaphore semp = new Semaphore(5); // 模拟20个客户端访问
for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可
semp.acquire();
System.out.println("Accessing: " + NO);
Thread.sleep((long) (Math.random() * 10000));
// 访问完后,释放
semp.release();
} catch (InterruptedException e) {
}
}
};
exec.execute(run);
} // 退出线程池
exec.shutdown();
}
}

Java线程间怎么实现同步的更多相关文章

  1. Java并发——线程间通信与同步技术

    传统的线程间通信与同步技术为Object上的wait().notify().notifyAll()等方法,Java在显示锁上增加了Condition对象,该对象也可以实现线程间通信与同步.本文会介绍有 ...

  2. Java 线程间通讯(共享变量方式)

    Java线程间通讯,最常用的方式便是共享变量方式,多个线程共享一个静态变量就可以实现在线程间通讯,但是这需要注意的就是线程同步问题. 一.没考虑线程同步: package com.wyf; publi ...

  3. Java线程间通信-回调的实现方式

    Java线程间通信-回调的实现方式   Java线程间通信是非常复杂的问题的.线程间通信问题本质上是如何将与线程相关的变量或者对象传递给别的线程,从而实现交互.   比如举一个简单例子,有一个多线程的 ...

  4. 说说Java线程间通信

    序言 正文 [一] Java线程间如何通信? 线程间通信的目标是使线程间能够互相发送信号,包括如下几种方式: 1.通过共享对象通信 线程间发送信号的一个简单方式是在共享对象的变量里设置信号值:线程A在 ...

  5. 说说 Java 线程间通信

    序言 正文 一.Java线程间如何通信? 线程间通信的目标是使线程间能够互相发送信号,包括如下几种方式: 1.通过共享对象通信 线程间发送信号的一个简单方式是在共享对象的变量里设置信号值:线程A在一个 ...

  6. Java线程间通信方式剖析——Java进阶(四)

    原创文章,同步发自作者个人博客,转载请在文章开头处以超链接注明出处 http://www.jasongj.com/java/thread_communication/ CountDownLatch C ...

  7. 【JAVA线程间通信技术】

    之前的例子都是多个线程执行同一种任务,下面开始讨论多个线程执行不同任务的情况. 举个例子:有个仓库专门存储货物,有的货车专门将货物送往仓库,有的货车则专门将货物拉出仓库,这两种货车的任务不同,而且为了 ...

  8. Java线程间通信之wait/notify

    Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式.我们来看下相关定义: w ...

  9. java线程间通信:一个小Demo完全搞懂

    版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程系列文章只是自己知识的总结梳理,都是最基础的玩意,已经掌握熟练的可以绕过. 一.从一个小Demo说起 上篇我们聊到了Java多线程的同步 ...

随机推荐

  1. 20155217 实验四《Java面向对象程序设计》实验报告

    20155217 实验四<Java面向对象程序设计>实验报告 一.实验内容 1.基于Android Studio开发简单的Android应用并部署测试; 2.了解Android.组件.布局 ...

  2. QT-2D编程

    QT-[转]2D编程 Qt中提供了强大的2D绘图系统,可以使用相同的API在屏幕上和绘图·设备上进行绘制,主要基于QPainter.QPainterDevice和QPainterEngine这3个类. ...

  3. 【BZOJ3110】【LG3332】[ZJOI2013]K大数查询

    [BZOJ3110][LG3332][ZJOI2013]K大数查询 题面 洛谷 BZOJ 题解 和普通的整体分治差不多 用线段树维护一下每个查询区间内大于每次二分的值\(mid\)的值即可 然后再按套 ...

  4. Zabbix学习之路(三)之使用SMTP发送邮件报警及定制邮件报警内容

    1.设置邮件报警的思路 (1)设置触发器(Trigger)-->触发后需要执行的动作(Action) 触发器使用逻辑表达式来评估通过 item 获取到得数据是处于哪种状态.在触发器表达式中我们可 ...

  5. Yii2 使用 faker 生成假数据

    测试过程中有时候需要生成大量的假数据,faker 是一个生成假数据的类库,可以生成姓名,电话,IP地址,密码,ISBN等等你能想到的或者你想不到的各种类型的假数据. Yii2.0已经集成该类库,不用再 ...

  6. Sublime Text3添加右键

    在Sublime Text3安装目录下新建一个文件 sublime_addright.inf 文件内容: [Version] Signature="$Windows NT$" [D ...

  7. 180724-统计JVM进程中线程数两种方式小记

    I. 统计进程中的线程数 相关系列博文推荐: 180711-JVM定位分析CPU性能消耗 180704-JDK常用监控参数 jvm调优的工具介绍 1. proc查询 /proc 目录以可读文本文件形式 ...

  8. Java EE平台介绍(译)

    Java EE平台介绍 2.1 企业应用总览 这一部分将对企业应用及其设计和开发进行简单介绍. 就像之前说的,Java EE 平台是为了帮助开发者开发大规模.多层次.可伸缩.服务可靠.网络安全的应用而 ...

  9. vue cli 3 +jquery

    const webpack = require('webpack')module.exports = { // baseUrl type:{string} default:'/' // 将部署应用程序 ...

  10. C# 如何使用 RabbitMQ 实现消息收发

    本文是基于http://www.cnblogs.com/cheng-lei/articles/7274513.html的项目结构进行搭建的,了解之前请先阅读http://www.cnblogs.com ...