首页 > 其他分享 >线程间通信

线程间通信

时间:2023-10-28 22:44:17浏览次数:36  
标签:Thread number InterruptedException 间通信 线程 new 唤醒

线程间通信

多线程编程步骤(中)

第一,创建资源类,创建属性和操作方法;第二,在资源操作方法,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 < 25; i++) {
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "aa").start();

        new Thread(() -> {
            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 < 10; i++) {
                try {
                    shareByLock.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "aa").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    shareByLock.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "bb").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    shareByLock.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "cc").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    shareByLock.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "dd").start();

    }
}

只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。

标签:Thread,number,InterruptedException,间通信,线程,new,唤醒
From: https://www.cnblogs.com/changming06/p/17794788.html

相关文章

  • Java基础 线程池
    线程池主要核心原理:①创建一个池子,池子中是空的②提交任务时,池子会创建新的线程对象来执行任务,当任务执行完毕,线程会还给池子,下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可③但是如果提交任务时,池子中没有空闲线程,并且也无法创建新的线程的时候,任务就会排队......
  • [Java]Java初学之多线程03--同步与锁
    Intro本篇文章主要关于多线程"同步"以及"锁"的相关内容~正文同步(Synchronize)概念“同步”是基于“并发”的需求而出现的所谓并发,就是同一个对象被多个线程同时操作,比如两个人同时从同一个账户取钱,再比如春运抢票。多个线程同时使用一个资源,必然会造成混乱。想象一下从前......
  • 线程池的线程数应该怎么配置?有哪几种常见的线程池?
    一、线程池的线程数应该怎么配置?线程在Java中属于稀缺资源,线程池不是越大越好也不是越小越好。任务分为计算密集型、IO密集型、混合型。1.计算密集型:大部分都在用CPU跟内存,加密,逻辑操作业务处理等。2.IO密集型:数据库链接,网络通讯传输等。一般的经验,不同类型线程池的参数配置:1、......
  • rust 创建多线程web server
    创建一个httpserver,处理http请求。创建一个单线程的web服务webserver中主要的两个协议是http和tcp。tcp是底层协议,http是构建在tcp之上的。通过std::net库创建一个tcp连接的监听对象,监听地址为127.0.0.1:8080.usestd::net::TcpListener;fnmain(){l......
  • 前端多线程处理——async/await
    async从字面上看就是“异步”,它放在函数定义之前,是使该函数在调用时开一个子线程,以不影响主线程的运行。而await经常和async组合使用,在async定义的函数中来等待需要时间运行的代码(如ajax请求、Promise对象)的运行结果,以做后续的处理。  如下面的返回Promise对象......
  • Python中最常用的5种线程锁,你都会用吗
    对于日常开发者来讲很少会使用到本章节的内容,但是对框架作者等是必备知识,同时也是高频的面试常见问题。1.线程安全线程安全是多线程或多进程编程中的一个概念,在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现......
  • 三种线程安全的List
    在单线程开发环境中,我们经常使用ArrayList作容器来存储我们的数据,但它不是线程安全的,在多线程环境中使用它可能会出现意想不到的结果。 总结获取线程安全的List我们可以通过Vector、Collections.synchronizedList()方法和CopyOnWriteArrayList三种方式读多写少的情况下,推荐使用......
  • Java基础 多线程的 6 种状态
       Java的虚拟机当中没有定义运行状态,因为当线程抢夺到CPU执行权的时候,虚拟机会把当前线程交给操作系统管理,虚拟机就不管了。 ......
  • Java基础 当某一个线程执行代码时发现锁已经被锁住了,该线程会怎么样?
    当一个线程尝试获取一个已经被其他线程锁住的锁时,它的行为取决于所使用的编程语言和锁的类型。一般情况下,有以下几种可能的行为:1.阻塞等待:线程会被阻塞,直到锁变为可用。这是最常见的情况,通常用于互斥锁。在Java中,可以使用synchronized关键字或ReentrantLock类来实现这种行为。2.......
  • 线程和进程的区别
    进程和线程是操作系统中重要的概念,都是操作系统资源分配的基本单位,但它们有以下区别:地址空间和资源拥有:同一进程的线程共享本进程的地址空间和资源,而进程之间则是独立的。通信:同一进程内的线程之间可以直接读写彼此的数据空间,便于高效协作;不同进程间则需要借助中间件(如消息队列......