线程间通信
主要通过wait()等待和notify()通知实现
多线程编程步骤
- 创建资源类,在资源类创建属性和操作方法
- 在资源类操作方法中
- 判断
- 干活
- 通知
- 创建多个线程,调用资源类方法
- 防止虚假唤醒问题(wait方法要在while中判断)
例子
有两个线程
实现对一个初始值为0的变量
一个线程对值+1
一个线程对值-1
synchronized关键字实现
class Share{
private int number = 0;
public synchronized void incr(){
//判断
while (number != 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//干活
number++;
System.out.println(Thread.currentThread().getName()+":"+number);
//通知其他线程
this.notifyAll();
}
public synchronized void decr(){
//判断
while (number != 1){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//干活
number--;
System.out.println(Thread.currentThread().getName()+":"+number);
//通知
this.notifyAll();
}
}
public class sync {
public static void main(String[] args) {
Share ticket = new Share();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
ticket.incr();
}
}
},"加操作").start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
ticket.decr();
}
}
},"减操作").start();
}
}
Lock接口实现
class ShareLock{
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
//+1
public void incr(){
lock.lock();
try {
//判断
while (number != 0){
condition.await();
}
//干活
number++;
System.out.println(Thread.currentThread().getName()+":"+number);
//通知
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//-1
public void desc(){
lock.lock();
try {
//判断
while (number != 1){
condition.await();
}
//干活
number--;
System.out.println(Thread.currentThread().getName()+":"+number);
//通知
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class lock {
public static void main(String[] args) {
ShareLock ticket = new ShareLock();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
ticket.incr();
}
}
},"加操作").start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
ticket.desc();
}
}
},"减操作").start();
}
}
线程间的定制化通信
例子
启动三个线程,按照一定顺序执行
A线程打印5次,B线程打印10次,C打印15次
进行10轮
class ShareResource{
//定义标志位
private int flag = 1;//1 AA 2 BB 3 CC
//创建lock
private final Lock lock = new ReentrantLock();
//创建三个condition
private final Condition c1 = lock.newCondition();
private final Condition c2 = lock.newCondition();
private final Condition c3 = lock.newCondition();
//打印5次
public void print5(int loop){
lock.lock();
try {
//判断
while (flag != 1){
c1.await();
}
//干活
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + "::" + i + " 轮数:" + loop);
}
//通知
flag = 2;
c2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//打印10次
public void print10(int loop){
lock.lock();
try {
//判断
while (flag != 2){
c2.await();
}
//干活
for (int i = 1; i <= 10; i++) {
System.out.println(Thread.currentThread().getName() + "::" + i + " 轮数:" + loop);
}
//通知
flag = 3;
c3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//打印15次
public void print15(int loop){
lock.lock();
try {
//判断
while (flag != 3){
c3.await();
}
//干活
for (int i = 1; i <= 15; i++) {
System.out.println(Thread.currentThread().getName() + "::" + i + " 轮数:" + loop);
}
//通知
flag = 1;
c1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class customize {
public static void main(String[] args) {
ShareResource shareResource = new ShareResource();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
shareResource.print5(i);
}
},"A1").start();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
shareResource.print10(i);
}
},"B2").start();
new Thread(() -> {
for (int i = 1; i <= 10; i++) {
shareResource.print15(i);
}
},"C3").start();
}
}