线程间通信多线程编程步骤(中)
第一,创建资源类,创建属性和操作方法;第二,在资源操作方法,1)判断 2)工作 3)通知;第三,创建多线程调用资源类的方法。
案例
要求,有两个线程,实现对一个初始值为0的变量,一个线程对值+1,一个线程对值-1。
代码实现
/** * @author 长名06 * @version 1.0 * 线程通信案例 两个线程对一个值进行 decr incr * 用synchronized关键字实现 */class Share { private int number; public synchronized void incr() throws InterruptedException { /** * 这样写,会出现虚假唤醒问题,因为如果当前线程被等待,然后被唤醒时,if语句,就不会再次进行判断 * 有可能出现,此时的number != 0 当时依旧进行了 +1操作 减方法类似 * wait()方法再api文档中,就提醒,在一个参数版本中,中断和虚假唤醒是可能的,并且该方法应该始终在循环中使用: * 线程在哪里被阻塞就会在哪里,被唤醒,也就是说线程被阻塞时,是满足number!= 0,所以阻塞,但是因为一个线程执行完后,释 * 放锁,然后唤醒等待的线程,是随机唤醒的,有可能当前+1的条件依旧不满足,但是系统却唤醒了该线程,因为是if语句,在 * this.wait()处被唤醒,程序继续执行,导致其实条件不满足,却执行了+1操作,所以使用while()循环进行判断,只能当条件满 * 足且线程被唤醒才执行incr方法 * if (number != 0){//条件 * this.wait(); * } */ while (number != 0) { this.wait(); } //加1 number++; System.out.println(Thread.currentThread().getName() + "\t" + number); //通知其他线程 this.notifyAll(); } public synchronized void decr() throws InterruptedException { while (number != 1) { this.wait(); } //减1 number--; System.out.println(Thread.currentThread().getName() + "\t" + number); //通知其他线程 this.notifyAll(); }}public class ThreadDemo { public static void main(String[] args) { Share share = new Share(); new Thread(() -> { for (int i = 0; i { for (int i = 0; i < 25; i++) { try { share.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "bb").start(); }}
多线程编程步骤(下)
第一,创建资源类,创建属性和操作方法;第二,在资源操作方法,1) 判断 2)工作 3)通知;第三,创建多线程调用资源类的方法;第四,防止虚假唤醒问题。
Lock实现上述案例代码
import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author 长名06 * @version 1.0 *///第一步创建资源类,属性和操作方法class ShareByLock { private int number; //获得锁 private final ReentrantLock lock = new ReentrantLock(); //为当前锁,创建一个新的condition,并绑定到该锁上 private Condition condition = lock.newCondition(); public void incr() throws InterruptedException { //上锁 lock.lock(); //第二步 进行 // 1.判断(线程切换的条件) // 2.执行(线程执行的具体操作) // 3.通知(唤醒等待的其他线程) try { //判断 //第四步 防止虚假唤醒现象 while (number != 0) { condition.await(); } //执行 number++; System.out.println(Thread.currentThread().getName() + "\t" + number); //通知 condition.signalAll(); } finally { //解锁 lock.unlock(); } } public void decr() throws InterruptedException { //上锁 lock.lock(); try { //判断 while (number != 1) { condition.await(); } //执行 number--; System.out.println(Thread.currentThread().getName() + "\t" + number); //通知 condition.signalAll(); } finally { //解锁 lock.unlock(); } }}public class ThreadDemoByLock { public static void main(String[] args) { ShareByLock shareByLock = new ShareByLock(); //第三步 创建多个线程调用资源类的方法 new Thread(() -> { for (int i = 0; i { for (int i = 0; i { for (int i = 0; i { for (int i = 0; i < 10; i++) { try { shareByLock.decr(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "dd").start(); }}
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。