Java中如何实现线程通信
发表于:2025-02-09 作者:千家信息网编辑
千家信息网最后更新 2025年02月09日,今天就跟大家聊聊有关Java中如何实现线程通信,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1、synchronized加wait/notif
千家信息网最后更新 2025年02月09日Java中如何实现线程通信
今天就跟大家聊聊有关Java中如何实现线程通信,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
1、synchronized加wait/notify方式
/** * wait和notify的使用 * wait和notify必须应用在synchronized块或方法内 * 下面的代码向跳交谊舞一样互相控制着对方的输出 */public class MutiThread_WaitNotify { public static void main(String[] args) { final Object lock = new Object(); Thread a = new Thread(new Runnable(){ @Override public void run(){ synchronized (lock){ try{ lock.wait(); System.out.println("A-1"); lock.notify(); lock.wait(); System.out.println("A-2"); lock.notify(); lock.wait(); System.out.println("A-3"); lock.notify(); }catch(InterruptedException e){ e.printStackTrace(); } } } }); Thread b = new Thread(new Runnable(){ @Override public void run(){ synchronized (lock){ try{ System.out.println("B-1"); lock.notify(); lock.wait(); System.out.println("B-2"); lock.notify(); lock.wait(); System.out.println("B-3"); lock.notify(); lock.wait(); System.out.println("B-4"); }catch(InterruptedException e){ e.printStackTrace();; } } } }); a.start(); b.start(); }}
2、ReentrantLock加Condition方式
/** * ReentrantLock和Condition的使用 * 在使用Conditioin的await和signal时,必须将这两个方法写在ReentrantLock的lock方法之后 */public class MutiThread_ReentrantLock_Condition { public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); Condition condition = lock.newCondition(); int i=1; for(; i<=6; i++){ final int k = i; Thread t1 = new Thread(new Runnable() { @Override public void run() { try{ lock.lock(); System.out.println("ThreadNo:A" + k + " is locked"); // 通过condition.await将线程阻塞 condition.await(); }catch(InterruptedException e){ e.printStackTrace(); }finally{ lock.unlock(); System.out.println("ThreadNo:A"+k + " is unlocked"); } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { if(k == 6){ try{ lock.lock(); System.out.println("All Threads is signaled"); // 通过condition.signalAll唤醒所有线程 condition.signalAll(); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } }else{ System.out.println("threads can't signaled, wait a moment."); } } }); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } }}
3、闭锁方式
import java.util.concurrent.CountDownLatch;/** * 闭锁的使用 * 闭锁用于等待事件,当闭锁到达结束状态(本例中是闭锁的计数器值减为0)之前,所有线程都等待,当闭锁到达结束状态时,所有线程都通过 * 闭锁是一次性的,当闭锁到达结束状态后,将不会被重置,这个锁会永远打开并允许所有线程通过。 * 可以将代码中的NUM变量值变为2和4,分别试试什么效果 */public class MutiThread_CountDownLatch { public static void main(String[] args) { // 定义闭锁,并设置闭锁的计数器值为3 CountDownLatch lock = new CountDownLatch(3); // 循环定义3个线程 int NUM = 3; for(int i=1; i<=NUM; i++){ final int k = i; Thread a = new Thread(new Runnable(){ @Override public void run(){ try{ Thread.sleep(k * 1000); System.out.println("ThreadNo:A"+k); // 每个线程在休眠指定时间后将闭锁的计数器值减1,当闭锁的计数器值减到0时,闭所将被打开,从而使第二个循环中的所有线程才能通过 lock.countDown(); // 打印闭锁计数器的值 System.out.println("ThreadNo:A"+k+"; getCount:"+lock.getCount()); }catch(InterruptedException e){ e.printStackTrace(); } } }); a.start(); } // 循环定义2个线程 for(int i=1; i<=2; i++){ final int k = i; Thread b = new Thread(new Runnable(){ @Override public void run(){ try{ System.out.println("ThreadNo:B"+k+" is waiting..."); // 当闭锁的计数器值不为0时,线程将在此处被中断 lock.await(); // 当闭锁的计数器值等于0时,闭锁将被打开,所有等待的线程都将被唤醒 System.out.println("ThreadNo:B"+k+" is notify"); }catch(InterruptedException e){ e.printStackTrace(); } } }); b.start(); } }}
4、栅栏的方式
import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;/** * 栅栏的使用 * 栅栏用于等待线程,所有线程必须同时到达栅栏,才能继续执行 * 栅栏不是一次性的,可以被重置。 * 可以将代码中的NUM变量值变为5和7,分别试试什么效果 */public class MutiThread_CyclicBarrier { public static void main(String[] args) { // 定义栅栏,并设置栅栏需要等待的线程数为6 CyclicBarrier barrier = new CyclicBarrier(6); int NUM = 100; for(int i=1; i<=NUM; i++){ final int k = i; Thread t = new Thread(new Runnable() { @Override public void run() { try{ Thread.sleep(k * 1000); System.out.println("ThreadNo:"+k+" is waiting, getNumberWaiting:" + barrier.getNumberWaiting()); // 栅栏设置的等待线程数为6,当线程数不够6个时,所有线程将在此等待 barrier.await(); // 当线程数达到6个时,栅栏将被打开,所有线程都将被唤醒 System.out.println("ThreadNo:"+k+" is notify"); // 栅栏被重置,以便下次继续使用 barrier.reset(); }catch(InterruptedException e){ e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }); t.start(); } }}
5、信号量的方式
import java.util.ArrayList;import java.util.List;import java.util.concurrent.Semaphore;/** * 信号量的使用 * 信号量用于控制同时访问某个资源的线程数量,信号量还可以用于实现某个资源池。 * 信号量管理者一组虚拟的许可,线程在执行操作时首先要获得许可,如果信号量的许可数量为0,那么accquire将阻塞直到有许可为止 * 信号量不是一次性的,当信号链的许可用完之后,可以通过release释放许可 */public class MutiThread_Semaphore { public static void main(String[] args) { // 定义信号量,并设置信号量的允许发放的最大许可数量为6 final Semaphore semaphore = new Semaphore(6); // 定义集合,当信号量未发放的许可数量大于0则允许线程向集合内添加元素 final Listset = new ArrayList<>(); int i = 1; while(true){ final int k = i++; Thread t = new Thread(new Runnable() { @Override public void run() { boolean res = false; try{ System.out.println("ThreadNo:A"+k+", availablePermits:"+semaphore.availablePermits()); // 当信号量允许发放的许可数量大于0,则会向集合内添加元素,否则将被中断于此 semaphore.acquire(); res = set.add("1"); System.out.println("ThreadNo:A"+k+" add item success"); }catch(InterruptedException e){ e.printStackTrace(); }finally{ if(!res){ semaphore.release(); } } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { if(semaphore.availablePermits() == 0){ // 如果信号量允许发放的许可数量等于0,则释放制定数量的许可 semaphore.release(3); //释放3个许可 System.out.println("ThreadNo:B"+k+" releasePermitNum:"+semaphore.availablePermits()); } } }); t.start(); t2.start(); System.out.println("the num of set:"+set.size()); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }}
A、join的使用
/** * join的使用 * 实现当调用join的线程执行完毕后,其他线程才能执行 */public class MutiThread_Join { public static void main(String[] args) { Thread a = new Thread(new Runnable(){ @Override public void run(){ printNumber("A"); } }); Thread b = new Thread(new Runnable(){ @Override public void run(){ printNumber("B"); } }); try{ a.start(); // a线程执行完毕后,b线程才能执行 a.join(); b.start(); }catch(InterruptedException e){ e.printStackTrace();; } } public static void printNumber(String s){ System.out.println(s+" print:"+s); }}
B、yield的使用
/** * yield,当一个线程中调用了这个方法后,这个线程就会把自己的CPU执行时间让给自己或其它线程, * 注意是让给自己或其它线程,并不是单纯让给其他线程。yield执行后,能让当前线程由运行状态 * 进入到就绪状态,将自己的CPU时间片让出来,让出来之后有可能是其它线程执行,也有可能是该线程 * 继续执行。优先级高的线程并不一定是首先执行,而是首先执行的概率会高一些。优先级在大量线程 * 执行的时候才能体现的出来。 */public class MutiThread_yield { public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { for(int i=0;i<10;i++){ System.out.println("ThreadNo:A"+i); Thread.yield(); } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { for(int i=0;i<10;i++){ System.out.println("ThreadNo:B"+i); Thread.yield(); } } }); t1.setPriority(Thread.MIN_PRIORITY); t2.setPriority(Thread.MAX_PRIORITY); t1.start(); t2.start(); }}
看完上述内容,你们对Java中如何实现线程通信有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。
线程
信号
信号量
栅栏
数量
计数器
方式
状态
方法
一次性
代码
内容
时间
循环
通信
优先级
元素
同时
效果
资源
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
湖北定制化国产服务器直销厂家
开封客户管理软件开发
浦东新区机电软件开发产品介绍
陕西智慧土地资产管理软件开发
互联网科技保经公司
东海有名的网络技术排名靠前
炒股软件开发公司排行榜
软件开发的评价指标
qq禁用服务器
常用的企业网络安全技术
铜陵网络安全宣传周电信
服务器硬盘不组raid
服务器爆了
汉子解读 数据库
长沙派出所网络安全协议软件
用虚拟机做服务器稳定么
中宏网河南互联网科技集团
能源舰服务器
服务器磁盘定位与屏蔽
徐汇区常规软件开发定制收费
3u服务器批发供应
福建营销软件开发管理
福州欣翼网络技术有限公司
网络安全法六十四条处罚
网络安全法的属于法律是什么
软件开发过程管理图书
在技术上如何学习网络技术
中国电子系统网络安全新闻
中宏网河南互联网科技集团
网络安全和舆论环境讲话稿